From db222a24ef3f688772a646219b67adba6bbe1e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?rich=CE=9Brd?= Date: Sat, 28 Oct 2023 19:37:53 -0400 Subject: [PATCH] fix(c-bindings): userdata (#785) --- examples/c-bindings/main.c | 236 +++++++++------ examples/c-bindings/main.h | 2 + library/c/README.md | 279 +++++++++--------- library/c/api.go | 74 +++-- library/c/api_discovery.go | 14 +- library/c/api_encoding.go | 22 +- library/c/api_filter.go | 22 +- library/c/api_legacy_filter.go | 14 +- library/c/api_lightpush.go | 10 +- library/c/api_relay.go | 52 ++-- library/c/api_store.go | 60 ++-- library/c/cgo_utils.c | 4 +- library/c/cgo_utils.go | 48 ++- library/c/cgo_utils.h | 4 +- library/encoding.go | 34 ++- library/filter.go | 5 +- library/lightpush.go | 2 +- library/node.go | 22 +- library/relay.go | 65 ++-- library/signals.c | 6 +- library/signals.go | 4 +- library/store.go | 17 +- waku/v2/protocol/content_filter.go | 4 +- .../subscription/subscriptions_map.go | 10 +- 24 files changed, 557 insertions(+), 453 deletions(-) diff --git a/examples/c-bindings/main.c b/examples/c-bindings/main.c index dd55f93a..71c2af79 100644 --- a/examples/c-bindings/main.c +++ b/examples/c-bindings/main.c @@ -1,41 +1,52 @@ -#include -#include -#include -#include -#include -#include -#include +#include "main.h" +#include "base64.h" #include "libgowaku.h" #include "nxjson.c" -#include "base64.h" -#include "main.h" +#include +#include -char *alicePrivKey = "0x4f012057e1a1458ce34189cb27daedbbe434f3df0825c1949475dec786e2c64e"; -char *alicePubKey = "0x0440f05847c4c7166f57ae8ecaaf72d31bddcbca345e26713ca9e26c93fb8362ddcd5ae7f4533ee956428ad08a89cd18b234c2911a3b1c7fbd1c0047610d987302"; +char *alicePrivKey = + "0x4f012057e1a1458ce34189cb27daedbbe434f3df0825c1949475dec786e2c64e"; +char *alicePubKey = + "0x0440f05847c4c7166f57ae8ecaaf72d31bddcbca345e26713ca9e26c93fb8362ddcd5ae7" + "f4533ee956428ad08a89cd18b234c2911a3b1c7fbd1c0047610d987302"; -char *bobPrivKey = "0xb91d6b2df8fb6ef8b53b51b2b30a408c49d5e2b530502d58ac8f94e5c5de1453"; -char *bobPubKey = "0x045eef61a98ba1cf44a2736fac91183ea2bd86e67de20fe4bff467a71249a8a0c05f795dd7f28ced7c15eaa69c89d4212cc4f526ca5e9a62e88008f506d850cccd"; +char *bobPrivKey = + "0xb91d6b2df8fb6ef8b53b51b2b30a408c49d5e2b530502d58ac8f94e5c5de1453"; +char *bobPubKey = + "0x045eef61a98ba1cf44a2736fac91183ea2bd86e67de20fe4bff467a71249a8a0c05f795d" + "d7f28ced7c15eaa69c89d4212cc4f526ca5e9a62e88008f506d850cccd"; +void on_error(int ret, const char *result, void *user_data) { + if (ret == 0) { + return; + } -char* result = NULL; -char* contentTopic; - -void handle_ok(const char* msg, size_t len) { - if (result != NULL) { - free(result); - } - result = malloc(len * sizeof(char) + 1); - strcpy(result, msg); + printf("function execution failed. Returned code: %d\n", ret); + exit(1); } -void handle_error(const char* msg, size_t len) { - printf("Error: %s\n", msg); +void on_response(int ret, const char *result, void *user_data) { + if (ret != 0) { + printf("function execution failed. Returned code: %d\n", ret); exit(1); + } + + if (user_data == NULL) + return; + + char **data_ref = (char **)user_data; + size_t len = strlen(result); + + if (*data_ref != NULL) + free(*data_ref); + + *data_ref = malloc(len * sizeof(char) + 1); + strcpy(*data_ref, result); } -void callBack(const char* signal, size_t len_0) -{ +void callBack(int ret, const char *signal, void *user_data) { // This callback will be executed each time a new message is received // Example signal: @@ -54,32 +65,43 @@ void callBack(const char* signal, size_t len_0) } }*/ - const nx_json *json = nx_json_parse((char*) signal, 0); + if (ret != 0) { + printf("function execution failed. Returned code: %d\n", ret); + exit(1); + } + + const nx_json *json = nx_json_parse((char *)signal, 0); const char *type = nx_json_get(json, "type")->text_value; - if (strcmp(type, "message") == 0) - { - const nx_json *wakuMsgJson = nx_json_get(nx_json_get(json, "event"), "wakuMessage"); - const char *contentTopic = nx_json_get(wakuMsgJson, "contentTopic")->text_value; + if (strcmp(type, "message") == 0) { + const nx_json *wakuMsgJson = + nx_json_get(nx_json_get(json, "event"), "wakuMessage"); + const char *contentTopic = + nx_json_get(wakuMsgJson, "contentTopic")->text_value; - if (strcmp(contentTopic, contentTopic) == 0) - { - char* msg = utils_extract_wakumessage_from_signal(wakuMsgJson); - WAKU_CALL(waku_decode_asymmetric(msg, bobPrivKey, handle_ok, handle_error)); + if (strcmp(contentTopic, "/example/1/default/rfc26") == 0) { + char *msg = utils_extract_wakumessage_from_signal(wakuMsgJson); - char *decodedMsg = strdup(result); + // Decode a message using asymmetric encryption + char *decodedMsg = NULL; + waku_decode_asymmetric(msg, bobPrivKey, on_response, (void *)&decodedMsg); const nx_json *dataJson = nx_json_parse(decodedMsg, 0); const char *pubkey = nx_json_get(dataJson, "pubkey")->text_value; const char *base64data = nx_json_get(dataJson, "data")->text_value; - + size_t data_len = b64_decoded_size(base64data); - char *data = malloc(data_len); - - b64_decode(base64data, (unsigned char *)data, data_len) ; + unsigned char *data = malloc(data_len); + + b64_decode(base64data, data, data_len); printf(">>> Received \"%s\" from %s\n", data, pubkey); + + free(msg); + free(decodedMsg); + free(data); + fflush(stdout); } } @@ -87,79 +109,113 @@ void callBack(const char* signal, size_t len_0) nx_json_free(json); } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { + // Set callback to be executed each time a message is received waku_set_event_callback(callBack); - char *configJSON = "{\"host\": \"0.0.0.0\", \"port\": 60000, \"logLevel\":\"error\", \"store\":true}"; - WAKU_CALL( waku_new(configJSON, handle_error) ); // configJSON can be NULL too to use defaults + // configJSON can be NULL too to use defaults. Any value not defined will have + // a default set + char *configJSON = "{\"host\": \"0.0.0.0\", \"port\": 60000, " + "\"logLevel\":\"error\", \"store\":true}"; + waku_new(configJSON, on_error, NULL); - WAKU_CALL(waku_start(handle_error) ); // Start the node, enabling the waku protocols + // Start the node, enabling the waku protocols + waku_start(on_error, NULL); - WAKU_CALL(waku_peerid(handle_ok, handle_error)); // Obtain the node peerID - char *peerID = strdup(result); - printf("PeerID: %s\n", result); + // Obtain the node's peerID + char *peerID = NULL; + waku_peerid(on_response, (void *)&peerID); + printf("PeerID: %s\n", peerID); - WAKU_CALL(waku_content_topic("example", 1, "default", "rfc26", handle_ok)); - contentTopic = strdup(result); - - WAKU_CALL(waku_connect("/dns4/node-01.gc-us-central1-a.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS", 0, handle_error)); // Connect to a node + // Obtain the node's multiaddresses + char *addresses = NULL; + waku_listen_addresses(on_response, (void *)&addresses); + printf("Addresses: %s\n", addresses); + + // Build a content topic + char *contentTopic = NULL; + waku_content_topic("example", 1, "default", "rfc26", on_response, + (void *)&contentTopic); + printf("Content Topic: %s\n", contentTopic); + + // Obtain the default pubsub topic + char *defaultPubsubTopic = NULL; + waku_default_pubsub_topic(on_response, (void *)&defaultPubsubTopic); + printf("Default pubsub topic: %s\n", defaultPubsubTopic); // To use dns discovery, and retrieve nodes from a enrtree url - WAKU_CALL( waku_dns_discovery("enrtree://AO47IDOLBKH72HIZZOXQP6NMRESAN7CHYWIBNXDXWRJRZWLODKII6@test.wakuv2.nodes.status.im", "", 0, handle_ok, handle_error)); // Discover Nodes - printf("Discovered nodes: %s\n", result); - - WAKU_CALL(waku_default_pubsub_topic(handle_ok)); - char *pubsubTopic = strdup(result); - printf("Default pubsub topic: %s\n", pubsubTopic); + char *discoveredNodes = NULL; + waku_dns_discovery("enrtree://" + "AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV" + "6SAYBM@test.waku.nodes.status.im", + "", 0, on_response, (void *)&discoveredNodes); + printf("Discovered nodes: %s\n", discoveredNodes); + + // Connect to a node + waku_connect("/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/30303/" + "p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ", + 0, on_response, NULL); // To see a store query in action: - /* - char query[1000]; - sprintf(query, "{\"pubsubTopic\":\"%s\", \"pagingOptions\":{\"pageSize\": 40, \"forward\":false}}", pubsubTopic); - WAKU_CALL(waku_store_query(query, NULL, 0, handle_ok, handle_error)); - printf("%s\n",result); - */ - - WAKU_CALL( waku_relay_subscribe(NULL, handle_error)); + // char query[1000]; + // sprintf(query, + // "{\"pubsubTopic\":\"%s\", \"pagingOptions\":{\"pageSize\": 40, " + // "\"forward\":false}}", + // pubsubTopic); + // char *query_result = NULL; + // waku_store_query(query, NULL, 0, on_response, (void*)&query_result); + // printf("%s\n", query_result); + char contentFilter[1000]; + sprintf(contentFilter, + "{\"pubsubTopic\":\"%s\",\"contentTopics\":[\"%s\"]}", + defaultPubsubTopic, contentTopic); + waku_relay_subscribe(contentFilter, on_error, NULL); int i = 0; int version = 1; - while (i < 5) - { + while (i < 5) { i++; char wakuMsg[1000]; - char *msgPayload = b64_encode("Hello World!", 12); + unsigned char plain_text[] = "Hello World!"; + char *msgPayload = b64_encode(&plain_text[0], 12); - sprintf(wakuMsg, "{\"payload\":\"%s\",\"contentTopic\":\"%s\",\"timestamp\":%"PRIu64"}", msgPayload, contentTopic, nowInNanosecs()); + // Build the waku message + sprintf(wakuMsg, + "{\"payload\":\"%s\",\"contentTopic\":\"%s\",\"timestamp\":%" PRIu64 + "}", + msgPayload, contentTopic, nowInNanosecs()); free(msgPayload); + // Use asymmetric encryption to encrypt the waku message + char *encodedMessage = NULL; + waku_encode_asymmetric(wakuMsg, bobPubKey, alicePrivKey, on_response, + (void *)&encodedMessage); - WAKU_CALL(waku_encode_asymmetric(wakuMsg, bobPubKey, alicePrivKey, handle_ok, handle_error)); - char *encodedMessage = strdup(result); - - WAKU_CALL(waku_relay_publish(encodedMessage, NULL, 0, handle_ok, handle_error)); // Broadcast via waku relay - printf("C\n"); - - char *messageID = strdup(result); - printf("MessageID: %s\n",messageID); - - free(messageID); + // Broadcast via waku relay + char *messageID = NULL; + waku_relay_publish(encodedMessage, defaultPubsubTopic, 0, on_response, + (void *)&messageID); + printf("MessageID: %s\n", messageID); sleep(1); } - - // To retrieve messages from local store, set store:true in the node config, and use waku_store_local_query - /* - char query[1000]; - sprintf(query, "{\"pubsubTopic\":\"%s\", \"pagingOptions\":{\"pageSize\": 40, \"forward\":false}}", pubsubTopic); - WAKU_CALL(waku_store_local_query(query, handle_ok, handle_error)); - printf("%s\n",result); - */ + // To retrieve messages from local store, set store:true in the node + // config, and use waku_store_local_query + // char query2[1000]; + // sprintf(query2, + // "{\"pubsubTopic\":\"%s\", \"pagingOptions\":{\"pageSize\": 40, " + // "\"forward\":false}}", + // pubsubTopic); + // char *local_result = NULL; + // waku_store_local_query(query2, on_response, (void*)&local_result); + // printf("%s\n", local_result); + + // Stop the node's execution + waku_stop(on_response, NULL); + + // TODO: free all char* - WAKU_CALL(waku_stop(handle_error)); - return 0; } diff --git a/examples/c-bindings/main.h b/examples/c-bindings/main.h index 66fb1f69..977359f6 100644 --- a/examples/c-bindings/main.h +++ b/examples/c-bindings/main.h @@ -2,6 +2,8 @@ #define MAIN_H #include +#include +#include #include "nxjson.c" /// Convert seconds to nanoseconds diff --git a/library/c/README.md b/library/c/README.md index 4d23aa68..83d3ead6 100644 --- a/library/c/README.md +++ b/library/c/README.md @@ -23,10 +23,10 @@ consume them. All the API functions require passing callbacks which will be executed depending on the result of the execution result. These callbacks are defined as ```c -typedef void (*WakuCallBack) (const char* msg, size_t len_0); +typedef void (*WakuCallBack) (int ret_code, const char* msg, void * user_data); ``` -With `msg` containing a `\0` terminated string, and `len_0` the length of this string. The format of the data sent to these callbacks -will depend on the function being executed. The data can be characters, numeric or json. +With ret_code containing a status code indicating the execution result, `msg` containing a `\0` terminated string. The format of the data sent to these callbacks will depend on the function being executed. The data for succesful results can be characters, numeric or json. +If the function being invoked returns an error, `msg` will contain the error string. ### Status Codes The API functions return an integer with status codes depending on the execution result. The following status codes are defined: @@ -74,21 +74,21 @@ Fields: - `data`: Decrypted message payload base64 encoded, - `padding`: Padding base64 encoded. -### `FilterSubscription` type +### `ContentFilter` type -The criteria to create subscription to a filter full node in JSON Format: +The criteria to create subscription in relay protocol or to a filter full node in JSON Format: ```ts { contentTopics: string[]; - pubsubTopic: string; + pubsubTopic?: string; } ``` Fields: - `contentTopics`: Array of content topics. -- `topic`: Optional pubsub topic when using contentTopics as per Autosharding. In case of named or static-sharding, pubSub topic is mandatory. +- `pubsubTopic`: Optional pubsub topic when using contentTopics as per Autosharding. In case of named or static-sharding, pubSub topic is mandatory. ### `LegacyFilterSubscription` type @@ -97,18 +97,18 @@ The criteria to create subscription to a filter full node in JSON Format: ```ts { - contentFilters: ContentFilter[]; + contentFilters: LegacyContentFilter[]; pubsubTopic: string?; } ``` Fields: -- `contentFilters`: Array of [`ContentFilter`](#contentfilter-type) being subscribed to / unsubscribed from. +- `contentFilters`: Array of [`LegacyContentFilter`](#legacycontentfilter-type) being subscribed to / unsubscribed from. - `topic`: Optional pubsub topic. -### `ContentFilter` type +### `LegacyContentFilter` type ```ts { @@ -127,7 +127,7 @@ Criteria used to retrieve historical messages ```ts interface StoreQuery { pubsubTopic?: string; - contentFilters?: ContentFilter[]; + contentTopics: string[]; startTime?: number; endTime?: number; pagingOptions?: PagingOptions @@ -137,7 +137,7 @@ interface StoreQuery { Fields: - `pubsubTopic`: The pubsub topic on which messages are published. -- `contentFilters`: Array of [`ContentFilter`](#contentfilter-type) to query for historical messages, +- `contentTOpics`: Array of content topics to query for historical messages, - `startTime`: The inclusive lower bound on the timestamp of queried messages. This field holds the Unix epoch time in nanoseconds. - `endTime`: The inclusive upper bound on the timestamp of queried messages. This field holds the Unix epoch time in nanoseconds. - `pagingOptions`: Paging information in [`PagingOptions`](#pagingoptions-type) format. @@ -216,7 +216,6 @@ For example: { "type": "message", "event": { - "subscriptionId": 1, "pubsubTopic": "/waku/2/default-waku/proto", "messageId": "0x6496491e40dbe0b6c3a2198c2426b16301688a2daebc4f57ad7706115eac3ad1", "wakuMessage": { @@ -249,15 +248,15 @@ Type of `event` field for a `message` event: - `messageId`: The message id. - `wakuMessage`: The message in [`JsonMessage`](#jsonmessage-type) format. -### `extern void waku_set_event_callback(void* cb)` +### `extern void waku_set_event_callback(WakuCallBack cb)` Register callback to act as event handler and receive application signals, which are used to react to asynchronous events in Waku. **Parameters** -1. `void* cb`: callback that will be executed when an async event is emitted. - The function signature for the callback should be `void myCallback(char* jsonSignal)` +1. `WakuCallBack cb`: callback that will be executed when an async event is emitted. + The function signature for the callback should be `void myCallback(char* signal, void * user_data)` ## Node management @@ -481,7 +480,7 @@ If a key is `undefined`, or `null`, a default value will be set. If using `secur - `keyPath`: secure websocket key path -### `extern int waku_new(char* jsonConfig, WakuCallBack onErrCb)` +### `extern int waku_new(char* jsonConfig, WakuCallBack onErrCb void* userData)` Instantiates a Waku node. @@ -491,69 +490,72 @@ Instantiates a Waku node. Type [`JsonConfig`](#jsonconfig-type). It can be `NULL` to use defaults. 2. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_start(WakuCallBack onErrCb)` +### `extern int waku_start(WakuCallBack onErrCb void* userData)` Start a Waku node mounting all the protocols that were enabled during the Waku node instantiation. **Parameters** 1. `WakuCallBack onErrCb`: callback to be executed if the function fails +2. `void* userData`: used to pass custom information to the callback function + **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_stop(WakuCallBack onErrCb)` +### `extern int waku_stop(WakuCallBack onErrCb void* userData)` Stops a Waku node. **Parameters** 1. `WakuCallBack onErrCb`: callback to be executed if the function fails +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_peerid(WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_peerid(WakuCallBack cb, void* userData)` Get the peer ID of the waku node. **Parameters** -1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -2. `WakuCallBack onErrCb`: callback to be executed if the function fails +1. `WakuCallBack cb`: callback to be executed. +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the base58 encoded peer ID, for example `QmWjHKUrXDHPCwoWXpUZ77E8o6UbAoTTZwf1AD1tDC4KNP`. -If the function is executed succesfully, `onOkCb` will receive the base58 encoded peer ID, for example `QmWjHKUrXDHPCwoWXpUZ77E8o6UbAoTTZwf1AD1tDC4KNP` - -### `extern int waku_listen_addresses(WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_listen_addresses(WakuCallBack cb, void* userData)` Get the multiaddresses the Waku node is listening to. **Parameters** -1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -2. `WakuCallBack onErrCb`: callback to be executed if the function fails +1. `WakuCallBack cb`: callback to be executed +2. `void* userData`: used to pass custom information to the callback function + **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive a json array of multiaddresses. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive a json array of multiaddresses. The multiaddresses are `string`s. - For example: - ```json [ "/ip4/127.0.0.1/tcp/30303", @@ -565,7 +567,7 @@ For example: ## Connecting to peers -### `extern int waku_add_peer(char* address, char* protocolId, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_add_peer(char* address, char* protocolId, WakuCallBack cb, void* userData)` Add a node multiaddress and protocol to the waku node's peerstore. @@ -573,18 +575,17 @@ Add a node multiaddress and protocol to the waku node's peerstore. 1. `char* address`: A multiaddress (with peer id) to reach the peer being added. 2. `char* protocolId`: A protocol we expect the peer to support. -3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -4. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `WakuCallBack cb`: callback to be executed +4. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the base 58 peer ID of the peer that was added. - +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the base 58 peer ID of the peer that was added. For example: `QmWjHKUrXDHPCwoWXpUZ77E8o6UbAoTTZwf1AD1tDC4KNP` -### `extern int waku_connect(char* address, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_connect(char* address, int timeoutMs, WakuCallBack onErrCb void* userData)` Dial peer using a multiaddress. @@ -596,12 +597,13 @@ Dial peer using a multiaddress. the execution will be canceled and an error returned. Use `0` for no timeout. 3. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_connect_peerid(char* peerId, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_connect_peerid(char* peerId, int timeoutMs, WakuCallBack onErrCb void* userData)` Dial peer using its peer ID. @@ -616,12 +618,13 @@ Dial peer using its peer ID. the execution will be canceled and an error returned. Use `0` for no timeout. 3. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_disconnect(char* peerId, WakuCallBack onErrCb)` +### `extern int waku_disconnect(char* peerId, WakuCallBack onErrCb void* userData)` Disconnect a peer using its peerID @@ -629,39 +632,40 @@ Disconnect a peer using its peerID 1. `char* peerID`: Peer ID to disconnect. 2. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_peer_cnt(WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_peer_cnt(WakuCallBack cb, void* userData)` Get number of connected peers. **Parameters** -1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -2. `WakuCallBack onErrCb`: callback to be executed if the function fails +1. `WakuCallBack cb`: callback to be executed +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the number of connected peers. -If the function is executed succesfully, `onOkCb` will receive the number of connected peers. - -### `extern int waku_peers(WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_peers(WakuCallBack cb, void* userData)` Retrieve the list of peers known by the Waku node. **Parameters** -1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -2. `WakuCallBack onErrCb`: callback to be executed if the function fails +1. `WakuCallBack cb`: callback to be executed if the function is succesful +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive a json array with the list of peers. -This list has this format: +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive a json array with the list of peers. +The list of peers has this format: ```json [ @@ -682,7 +686,7 @@ This list has this format: ## Waku Relay -### `extern int waku_content_topic(char* applicationName, unsigned int applicationVersion, char* contentTopicName, char* encoding, WakuCallBack onOkCb)` +### `extern int waku_content_topic(char* applicationName, unsigned int applicationVersion, char* contentTopicName, char* encoding, WakuCallBack onOkCb void* userData)` Create a content topic string according to [RFC 23](https://rfc.vac.dev/spec/23/). @@ -693,6 +697,7 @@ Create a content topic string according to [RFC 23](https://rfc.vac.dev/spec/23/ 3. `char* contentTopicName` 4. `char* encoding`: depending on the payload, use `proto`, `rlp` or `rfc26` 5. `WakuCallBack onOkCb`: callback to be executed if the function is succesful +6. `void* userData`: used to pass custom information to the callback function **Returns** @@ -704,7 +709,7 @@ If the function is executed succesfully, `onOkCb` will receive the content topic /{application-name}/{version-of-the-application}/{content-topic-name}/{encoding} ``` -### `extern int waku_pubsub_topic(char* name, char* encoding, WakuCallBack onOkCb)` +### `extern int waku_pubsub_topic(char* name, char* encoding, WakuCallBack onOkCb, void* userData)` Create a pubsub topic string according to [RFC 23](https://rfc.vac.dev/spec/23/). @@ -713,6 +718,7 @@ Create a pubsub topic string according to [RFC 23](https://rfc.vac.dev/spec/23/) 1. `char* name` 2. `char* encoding`: depending on the payload, use `proto`, `rlp` or `rfc26` 3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful +4. `void* userData`: used to pass custom information to the callback function **Returns** @@ -724,7 +730,7 @@ If the function is executed succesfully, `onOkCb` will receive the pubsub topic /waku/2/{topic-name}/{encoding} ``` -### `extern int waku_default_pubsub_topic(WakuCallBack onOkCb)` +### `extern int waku_default_pubsub_topic(WakuCallBack onOkCb void* userData)` Returns the default pubsub topic used for exchanging waku messages defined in [RFC 10](https://rfc.vac.dev/spec/10/). @@ -734,6 +740,7 @@ Returns the default pubsub topic used for exchanging waku messages defined in [R 1. `char* name` 2. `char* encoding`: depending on the payload, use `proto`, `rlp` or `rfc26` 3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful +4. `void* userData`: used to pass custom information to the callback function **Returns** @@ -741,8 +748,7 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible If the function is executed succesfully, `onOkCb` will receive the default pubsub topic: `/waku/2/default-waku/proto` - -### `extern int waku_relay_publish(char* messageJson, char* pubsubTopic, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_relay_publish(char* messageJson, char* pubsubTopic, int timeoutMs, WakuCallBack cb, void* userData)` Publish a message using Waku Relay. @@ -750,23 +756,21 @@ Publish a message using Waku Relay. 1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). 2. `char* pubsubTopic`: pubsub topic on which to publish the message. - If `NULL`, it uses the default pubsub topic. + If `NULL`, it derives the pubsub topic from content-topic based on autosharding. 3. `int timeoutMs`: Timeout value in milliseconds to execute the call. If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `0`. +4. `WakuCallBack cb`: callback to be executed +5. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - +If the function execution fails, `cb` will receive a string containing an error. If the function is executed succesfully, `onOkCb` will receive the message ID. -### `extern int waku_relay_enough_peers(char* pubsubTopic, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_relay_enough_peers(char* pubsubTopic, WakuCallBack cb, void* userData)` Determine if there are enough peers to publish a message on a given pubsub topic. @@ -774,42 +778,42 @@ Determine if there are enough peers to publish a message on a given pubsub topic 1. `char* pubsubTopic`: Pubsub topic to verify. If `NULL`, it verifies the number of peers in the default pubsub topic. -2. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -3. `WakuCallBack onErrCb`: callback to be executed if the function fails +2. `WakuCallBack cb`: callback to be executed +3. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - +If the function execution fails, `cb` will receive a string containing an error. If the function is executed succesfully, `onOkCb` will receive a string `boolean` indicating whether there are enough peers, i.e. `true` or `false` -### `extern int waku_relay_subscribe(char* topic, WakuCallBack onErrCb)` +### `extern int waku_relay_subscribe(char* filterJSON, WakuCallBack onErrCb, void* userData)` Subscribe to a Waku Relay pubsub topic to receive messages. **Parameters** -1. `char* topic`: Pubsub topic to subscribe to. - If `NULL`, it subscribes to the default pubsub topic. +1. `char* filterJSON`: JSON string containing the [`ContentFilter`](#contentfilter-type) with the criteria of the messages to receive 2. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_relay_topics(WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_relay_topics(WakuCallBack cb, void* userData)` Get the list of subscribed pubsub topics in Waku Relay. **Parameters** -1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -2. `WakuCallBack onErrCb`: callback to be executed if the function fails +1. `WakuCallBack cb`: callback to be executed +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive a json array of pubsub topics. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive a json array of pubsub topics. For example: @@ -843,16 +847,16 @@ For Example: } ``` -### `extern int waku_relay_unsubscribe(char* topic, WakuCallBack onErrCb)` +### `extern int waku_relay_unsubscribe(char* filterJSON, WakuCallBack onErrCb, void* userData)` -Closes the pubsub subscription to a pubsub topic. No more messages will be received +Closes the pubsub subscription to pubsub topic matching a criteria. No more messages will be received from this pubsub topic. **Parameters** -1. `char* pusubTopic`: Pubsub topic to unsubscribe from. - If `NULL`, unsubscribes from the default pubsub topic. +1. `char* filterJSON`: JSON string containing the [`ContentFilter`](#contentfilter-type) with the criteria of the messages to unsubscribe from 2. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `void* userData`: used to pass custom information to the callback function **Returns** @@ -861,13 +865,13 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible ## Waku Filter -### `extern int waku_filter_subscribe(char* filterJSON, char* peerID, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_filter_subscribe(char* filterJSON, char* peerID, int timeoutMs, WakuCallBack cb, void* userData)` Creates a subscription to a filter full node matching a content filter.. **Parameters** -1. `char* filterJSON`: JSON string containing the [`FilterSubscription`](#filtersubscription-type) to subscribe to. +1. `char* filterJSON`: JSON string containing the [`ContentFilter`](#contentfilter-type) with the criteria of the messages to receive 2. `char* peerID`: Peer ID to subscribe to. The peer must be already known. It must have been added before with [`waku_add_peer`](#extern-char-waku_add_peerchar-address-char-protocolid) @@ -877,14 +881,14 @@ Creates a subscription to a filter full node matching a content filter.. If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `WakuCallBack cb`: callback to be executed +5. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the following subscription details along with any partial errors. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the following subscription details along with any partial errors. For example: @@ -928,7 +932,7 @@ For Example: ``` -### `extern int waku_filter_ping(char* peerID, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_filter_ping(char* peerID, int timeoutMs, WakuCallBack onErrCb, void* userData)` Used to know if a service node has an active subscription for this client @@ -943,13 +947,14 @@ Used to know if a service node has an active subscription for this client the execution will be canceled and an error returned. Use `0` for no timeout. 3. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_filter_unsubscribe(filterJSON *C.char, char* peerID, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_filter_unsubscribe(filterJSON *C.char, char* peerID, int timeoutMs, WakuCallBack onErrCb, void* userData)` Sends a requests to a service node to stop pushing messages matching this filter to this client. It might be used to modify an existing subscription by providing a subset of the original filter criteria **Parameters** @@ -964,13 +969,14 @@ Sends a requests to a service node to stop pushing messages matching this filter the execution will be canceled and an error returned. Use `0` for no timeout. 4. `WakuCallBack onErrCb`: callback to be executed if the function fails +5. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. -### `extern int waku_filter_unsubscribe_all(char* peerID, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_filter_unsubscribe_all(char* peerID, int timeoutMs, WakuCallBack cb, void* userData)` Sends a requests to a service node (or all service nodes) to stop pushing messages @@ -985,14 +991,14 @@ Sends a requests to a service node (or all service nodes) to stop pushing messag If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -4. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `WakuCallBack cb`: callback to be executed +4. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive an array with information about the state of each unsubscription attempt (one per peer) +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive an array with information about the state of each unsubscription attempt (one per peer) For example: @@ -1009,7 +1015,7 @@ For example: ## Waku Legacy Filter -### `extern int waku_legacy_filter_subscribe(char* filterJSON, char* peerID, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_legacy_filter_subscribe(char* filterJSON, char* peerID, int timeoutMs, WakuCallBack onErrCb, void* userData)` Creates a subscription in a lightnode for messages that matches a content filter and optionally a [PubSub `topic`](https://github.com/libp2p/specs/blob/master/pubsub/README.md#the-topic-descriptor). @@ -1026,6 +1032,7 @@ Creates a subscription in a lightnode for messages that matches a content filter the execution will be canceled and an error returned. Use `0` for no timeout. 4. `WakuCallBack onErrCb`: callback to be executed if the function fails +5. `void* userData`: used to pass custom information to the callback function **Returns** @@ -1056,7 +1063,7 @@ For Example: } ``` -### `extern int waku_legacy_filter_unsubscribe(char* filterJSON, int timeoutMs, WakuCallBack onErrCb)` +### `extern int waku_legacy_filter_unsubscribe(char* filterJSON, int timeoutMs, WakuCallBack onErrCb, void* userData)` Removes subscriptions in a light node matching a content filter and, optionally, a [PubSub `topic`](https://github.com/libp2p/specs/blob/master/pubsub/README.md#the-topic-descriptor). @@ -1068,6 +1075,7 @@ Removes subscriptions in a light node matching a content filter and, optionally, the execution will be canceled and an error returned. Use `0` for no timeout. 3. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `void* userData`: used to pass custom information to the callback function **Returns** @@ -1075,7 +1083,7 @@ A status code. Refer to the [`Status codes`](#status-codes) section for possible ## Waku Lightpush -### `extern int waku_lightpush_publish(char* messageJSON, char* topic, char* peerID, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_lightpush_publish(char* messageJSON, char* topic, char* peerID, int timeoutMs, WakuCallBack cb, void* userData)` Publish a message using Waku Lightpush. @@ -1089,24 +1097,23 @@ Publish a message using Waku Lightpush. It must have been added before with [`waku_add_peer`](#extern-char-waku_add_peerchar-address-char-protocolid) or previously dialed with [`waku_connect_peer`](#extern-char-waku_connect_peerchar-address-int-timeoutms). Use `NULL` to automatically select a node. -3. `int timeoutMs`: Timeout value in milliseconds to execute the call. +4. `int timeoutMs`: Timeout value in milliseconds to execute the call. If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails - -Note: `messageJson.version` is overwritten to `0`. +5. `WakuCallBack cb`: callback to be executed +6. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the message ID. -If the function is executed succesfully, `onOkCb` will receive the message ID. ## Waku Store -### `extern int waku_store_query(char* queryJSON, char* peerID, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_store_query(char* queryJSON, char* peerID, int timeoutMs, WakuCallBack cb, void* userData)` Retrieves historical messages on specific content topics. This method may be called with [`PagingOptions`](#pagingoptions-type), to retrieve historical messages on a per-page basis. If the request included [`PagingOptions`](#pagingoptions-type), the node @@ -1124,16 +1131,16 @@ must contain a cursor pointing to the Index from which a new page can be request If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `WakuCallBack cb`: callback to be executed +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive a [`StoreResponse`](#storeresponse-type). -If the function is executed succesfully, `onOkCb` will receive a [`StoreResponse`](#storeresponse-type). - -### `extern int waku_store_local_query(char* queryJSON, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_store_local_query(char* queryJSON, WakuCallBack cb, void* userData)` Retrieves locally stored historical messages on specific content topics. This method may be called with [`PagingOptions`](#pagingoptions-type), to retrieve historical messages on a per-page basis. If the request included [`PagingOptions`](#pagingoptions-type), the node @@ -1147,18 +1154,18 @@ must contain a cursor pointing to the Index from which a new page can be request If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -4. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `WakuCallBack cb`: callback to be executed +2. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive a [`StoreResponse`](#storeresponse-type). +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive a [`StoreResponse`](#storeresponse-type). ## Encrypting messages -### `extern int waku_encode_symmetric(char* messageJson, char* symmetricKey, char* optionalSigningKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_encode_symmetric(char* messageJson, char* symmetricKey, char* optionalSigningKey, WakuCallBack cb, void* userData)` Encrypt a message using symmetric encryption and optionally sign the message @@ -1167,18 +1174,18 @@ Encrypt a message using symmetric encryption and optionally sign the message 1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). 2. `char* symmetricKey`: hex encoded secret key to be used for encryption. 3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `WakuCallBack cb`: callback to be executed +5. `void* userData`: used to pass custom information to the callback function Note: `messageJson.version` is overwritten to `1`. **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions -If the function is executed succesfully, `onOkCb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions - -### `extern int waku_encode_asymmetric(char* messageJson, char* publicKey, char* optionalSigningKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_encode_asymmetric(char* messageJson, char* publicKey, char* optionalSigningKey, WakuCallBack cb, void* userData)` Encrypt a message using asymmetric encryption and optionally sign the message @@ -1187,37 +1194,37 @@ Encrypt a message using asymmetric encryption and optionally sign the message 1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). 2. `char* publicKey`: hex encoded public key to be used for encryption. 3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `WakuCallBack cb`: callback to be executed +5. `void* userData`: used to pass custom information to the callback function Note: `messageJson.version` is overwritten to `1`. **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the encrypted waku message which can be broadcasted with relay or lightpush protocol publish functions ## Decrypting messages -### `extern int waku_decode_symmetric(char* messageJson, char* symmetricKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_decode_symmetric(char* messageJson, char* symmetricKey, WakuCallBack cb, void* userData)` Decrypt a message using a symmetric key **Parameters** 1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). 2. `char* symmetricKey`: 32 byte symmetric key hex encoded. -3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -4. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `WakuCallBack cb`: callback to be executed +4. `void* userData`: used to pass custom information to the callback function Note: `messageJson.version` is expected to be `1`. **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the decoded payload as a [`DecodedPayload`](#decodedpayload-type). +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the decoded payload as a [`DecodedPayload`](#decodedpayload-type). ```json @@ -1229,23 +1236,23 @@ If the function is executed succesfully, `onOkCb` will receive the decoded paylo } ``` -### `extern int waku_decode_asymmetric(char* messageJson, char* privateKey, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_decode_asymmetric(char* messageJson, char* privateKey, WakuCallBack cb, void* userData)` Decrypt a message using a secp256k1 private key **Parameters** 1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type). 2. `char* privateKey`: secp256k1 private key hex encoded. -3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -4. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `WakuCallBack cb`: callback to be executed +4. `void* userData`: used to pass custom information to the callback function Note: `messageJson.version` is expected to be `1`. **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - -If the function is executed succesfully, `onOkCb` will receive the decoded payload as a [`DecodedPayload`](#decodedpayload-type). +If the function execution fails, `cb` will receive a string containing an error. +If the function is executed succesfully, `cb` will receive the decoded payload as a [`DecodedPayload`](#decodedpayload-type). ```json { @@ -1258,7 +1265,7 @@ If the function is executed succesfully, `onOkCb` will receive the decoded paylo ## DNS Discovery -### `extern int waku_dns_discovery(char* url, char* nameserver, int timeoutMs, WakuCallBack onOkCb, WakuCallBack onErrCb)` +### `extern int waku_dns_discovery(char* url, char* nameserver, int timeoutMs, WakuCallBack cb, void* userData)` Returns a list of multiaddress and enrs given a url to a DNS discoverable ENR tree **Parameters** @@ -1270,16 +1277,15 @@ Returns a list of multiaddress and enrs given a url to a DNS discoverable ENR tr If the function execution takes longer than this value, the execution will be canceled and an error returned. Use `0` for no timeout. -4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful -5. `WakuCallBack onErrCb`: callback to be executed if the function fails +4. `WakuCallBack cb`: callback to be executed +3. `void* userData`: used to pass custom information to the callback function **Returns** A status code. Refer to the [`Status codes`](#status-codes) section for possible values. - +If the function execution fails, `cb` will receive a string containing an error. If the function is executed succesfully, `onOkCb` will receive an array objects describing the multiaddresses, enr and peerID each node found. - ```json [ { @@ -1296,13 +1302,14 @@ If the function is executed succesfully, `onOkCb` will receive an array objects ## DiscoveryV5 -### `extern int waku_discv5_update_bootnodes(char* bootnodes, WakuCallBack onErrCb)` +### `extern int waku_discv5_update_bootnodes(char* bootnodes, WakuCallBack onErrCb, void* userData)` Update the bootnode list used for discovering new peers via DiscoveryV5 **Parameters** 1. `char* bootnodes`: JSON array containing the bootnode ENRs i.e. `["enr:...", "enr:..."]` 2. `WakuCallBack onErrCb`: callback to be executed if the function fails +3. `void* userData`: used to pass custom information to the callback function **Returns** diff --git a/library/c/api.go b/library/c/api.go index 81ba8f57..e932dc04 100644 --- a/library/c/api.go +++ b/library/c/api.go @@ -6,11 +6,11 @@ package main #include // The possible returned values for the functions that return int -#define RET_OK 0 -#define RET_ERR 1 -#define RET_MISSING_CALLBACK 2 +static const int RET_OK = 0; +static const int RET_ERR = 1; +static const int RET_MISSING_CALLBACK = 2; -typedef void (*WakuCallBack) (const char* msg, size_t len_0); +typedef void (*WakuCallBack) (int ret_code, const char* msg, void * user_data); */ import "C" import ( @@ -21,10 +21,6 @@ import ( "github.com/waku-org/go-waku/waku/v2/protocol" ) -const retOk = C.RET_OK -const retErr = C.RET_ERR -const retMissingCallback = C.RET_MISSING_CALLBACK - func main() {} // Initialize a waku node. Receives a JSON string containing the configuration @@ -92,25 +88,25 @@ func main() {} // - dns4DomainName: the domain name resolving to the node's public IPv4 address. // //export waku_new -func waku_new(configJSON *C.char, onErrCb C.WakuCallBack) C.int { +func waku_new(configJSON *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.NewNode(C.GoString(configJSON)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Starts the waku node // //export waku_start -func waku_start(onErrCb C.WakuCallBack) C.int { +func waku_start(onErr C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.Start() - return execErrCB(onErrCb, err) + return onError(err, onErr, userData) } // Stops a waku node // //export waku_stop -func waku_stop(onErrCb C.WakuCallBack) C.int { +func waku_stop(onErr C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.Stop() - return execErrCB(onErrCb, err) + return onError(err, onErr, userData) } // Determine is a node is started or not @@ -126,96 +122,96 @@ func waku_is_started() C.int { type fn func() (string, error) -func singleFnExec(f fn, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func singleFnExec(f fn, cb C.WakuCallBack, userData unsafe.Pointer) C.int { result, err := f() if err != nil { - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } - return execOkCB(onOkCb, result) + return onSuccesfulResponse(result, cb, userData) } // Obtain the peer ID of the waku node // //export waku_peerid -func waku_peerid(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_peerid(cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.PeerID() - }, onOkCb, onErrCb) + }, cb, userData) } // Obtain the multiaddresses the wakunode is listening to // //export waku_listen_addresses -func waku_listen_addresses(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_listen_addresses(cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.ListenAddresses() - }, onOkCb, onErrCb) + }, cb, userData) } // Add node multiaddress and protocol to the wakunode peerstore // //export waku_add_peer -func waku_add_peer(address *C.char, protocolID *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_add_peer(address *C.char, protocolID *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.AddPeer(C.GoString(address), C.GoString(protocolID)) - }, onOkCb, onErrCb) + }, cb, userData) } // Connect to peer at multiaddress. if ms > 0, cancel the function execution if it takes longer than N milliseconds // //export waku_connect -func waku_connect(address *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_connect(address *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.Connect(C.GoString(address), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Connect to known peer by peerID. if ms > 0, cancel the function execution if it takes longer than N milliseconds // //export waku_connect_peerid -func waku_connect_peerid(peerID *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_connect_peerid(peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.ConnectPeerID(C.GoString(peerID), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Close connection to a known peer by peerID // //export waku_disconnect -func waku_disconnect(peerID *C.char, onErrCb C.WakuCallBack) C.int { +func waku_disconnect(peerID *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.Disconnect(C.GoString(peerID)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Get number of connected peers // //export waku_peer_cnt -func waku_peer_cnt(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_peer_cnt(cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { peerCnt, err := library.PeerCnt() return fmt.Sprintf("%d", peerCnt), err - }, onOkCb, onErrCb) + }, cb, userData) } // Create a content topic string according to RFC 23 // //export waku_content_topic -func waku_content_topic(applicationName *C.char, applicationVersion C.uint, contentTopicName *C.char, encoding *C.char, onOkCb C.WakuCallBack) C.int { +func waku_content_topic(applicationName *C.char, applicationVersion C.uint, contentTopicName *C.char, encoding *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { contentTopic, _ := protocol.NewContentTopic(C.GoString(applicationName), uint32(applicationVersion), C.GoString(contentTopicName), C.GoString(encoding)) - return execOkCB(onOkCb, contentTopic.String()) + return onSuccesfulResponse(contentTopic.String(), cb, userData) } // Create a pubsub topic string according to RFC 23 // //export waku_pubsub_topic -func waku_pubsub_topic(name *C.char, encoding *C.char, onOkCb C.WakuCallBack) C.int { +func waku_pubsub_topic(name *C.char, encoding *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { topic := library.PubsubTopic(C.GoString(name), C.GoString(encoding)) - return execOkCB(onOkCb, topic) + return onSuccesfulResponse(topic, cb, userData) } // Get the default pubsub topic used in waku2: /waku/2/default-waku/proto // //export waku_default_pubsub_topic -func waku_default_pubsub_topic(onOkCb C.WakuCallBack) C.int { - return execOkCB(onOkCb, library.DefaultPubsubTopic()) +func waku_default_pubsub_topic(cb C.WakuCallBack, userData unsafe.Pointer) C.int { + return onSuccesfulResponse(library.DefaultPubsubTopic(), cb, userData) } // Register callback to act as signal handler and receive application signals @@ -230,8 +226,8 @@ func waku_set_event_callback(cb C.WakuCallBack) { // Retrieve the list of peers known by the waku node // //export waku_peers -func waku_peers(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_peers(cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.Peers() - }, onOkCb, onErrCb) + }, cb, userData) } diff --git a/library/c/api_discovery.go b/library/c/api_discovery.go index 31171e98..c5d009ec 100644 --- a/library/c/api_discovery.go +++ b/library/c/api_discovery.go @@ -5,7 +5,11 @@ package main */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Returns a list of objects containing the peerID, enr and multiaddresses for each node found // @@ -17,17 +21,17 @@ import "github.com/waku-org/go-waku/library" // (in milliseconds) is reached, or an error will be returned // //export waku_dns_discovery -func waku_dns_discovery(url *C.char, nameserver *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_dns_discovery(url *C.char, nameserver *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.DNSDiscovery(C.GoString(url), C.GoString(nameserver), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } // Update the bootnode list used for discovering new peers via DiscoveryV5 // The bootnodes param should contain a JSON array containing the bootnode ENRs i.e. `["enr:...", "enr:..."]` // //export waku_discv5_update_bootnodes -func waku_discv5_update_bootnodes(bootnodes *C.char, onErrCb C.WakuCallBack) C.int { +func waku_discv5_update_bootnodes(bootnodes *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.SetBootnodes(C.GoString(bootnodes)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } diff --git a/library/c/api_encoding.go b/library/c/api_encoding.go index 6a9d03d2..a9c38ae9 100644 --- a/library/c/api_encoding.go +++ b/library/c/api_encoding.go @@ -4,24 +4,28 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Decode a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix // //export waku_decode_symmetric -func waku_decode_symmetric(messageJSON *C.char, symmetricKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_decode_symmetric(messageJSON *C.char, symmetricKey *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.DecodeSymmetric(C.GoString(messageJSON), C.GoString(symmetricKey)) - }, onOkCb, onErrCb) + }, cb, userData) } // Decode a waku message using a secp256k1 private key. The key must be a hex encoded string with "0x" prefix // //export waku_decode_asymmetric -func waku_decode_asymmetric(messageJSON *C.char, privateKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_decode_asymmetric(messageJSON *C.char, privateKey *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.DecodeAsymmetric(C.GoString(messageJSON), C.GoString(privateKey)) - }, onOkCb, onErrCb) + }, cb, userData) } // Encrypt a message with a secp256k1 public key. @@ -30,10 +34,10 @@ func waku_decode_asymmetric(messageJSON *C.char, privateKey *C.char, onOkCb C.Wa // The message version will be set to 1 // //export waku_encode_asymmetric -func waku_encode_asymmetric(messageJSON *C.char, publicKey *C.char, optionalSigningKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_encode_asymmetric(messageJSON *C.char, publicKey *C.char, optionalSigningKey *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.EncodeAsymmetric(C.GoString(messageJSON), C.GoString(publicKey), C.GoString(optionalSigningKey)) - }, onOkCb, onErrCb) + }, cb, userData) } // Encrypt a message with a 32 bytes symmetric key @@ -42,8 +46,8 @@ func waku_encode_asymmetric(messageJSON *C.char, publicKey *C.char, optionalSign // The message version will be set to 1 // //export waku_encode_symmetric -func waku_encode_symmetric(messageJSON *C.char, symmetricKey *C.char, optionalSigningKey *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_encode_symmetric(messageJSON *C.char, symmetricKey *C.char, optionalSigningKey *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.EncodeSymmetric(C.GoString(messageJSON), C.GoString(symmetricKey), C.GoString(optionalSigningKey)) - }, onOkCb, onErrCb) + }, cb, userData) } diff --git a/library/c/api_filter.go b/library/c/api_filter.go index 4a749699..caa26a45 100644 --- a/library/c/api_filter.go +++ b/library/c/api_filter.go @@ -4,7 +4,11 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Creates a subscription to a filter full node matching a content filter. // filterJSON must contain a JSON with this format: @@ -20,10 +24,10 @@ import "github.com/waku-org/go-waku/library" // It returns a json object containing the details of the subscriptions along with any errors in case of partial failures // //export waku_filter_subscribe -func waku_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.FilterSubscribe(C.GoString(filterJSON), C.GoString(peerID), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } // Used to know if a service node has an active subscription for this client @@ -32,9 +36,9 @@ func waku_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, onOkCb // (in milliseconds) is reached, or an error will be returned // //export waku_filter_ping -func waku_filter_ping(peerID *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_filter_ping(peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.FilterPing(C.GoString(peerID), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Sends a requests to a service node to stop pushing messages matching this filter to this client. @@ -51,9 +55,9 @@ func waku_filter_ping(peerID *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { // (in milliseconds) is reached, or an error will be returned // //export waku_filter_unsubscribe -func waku_filter_unsubscribe(filterJSON *C.char, peerID *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_filter_unsubscribe(filterJSON *C.char, peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.FilterUnsubscribe(C.GoString(filterJSON), C.GoString(peerID), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Sends a requests to a service node (or all service nodes) to stop pushing messages @@ -63,8 +67,8 @@ func waku_filter_unsubscribe(filterJSON *C.char, peerID *C.char, ms C.int, onErr // (in milliseconds) is reached, or an error will be returned // //export waku_filter_unsubscribe_all -func waku_filter_unsubscribe_all(peerID *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_filter_unsubscribe_all(peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.FilterUnsubscribeAll(C.GoString(peerID), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } diff --git a/library/c/api_legacy_filter.go b/library/c/api_legacy_filter.go index 4c0893f3..a88bc529 100644 --- a/library/c/api_legacy_filter.go +++ b/library/c/api_legacy_filter.go @@ -4,7 +4,11 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Creates a subscription to a light node matching a content filter and, optionally, a pubSub topic. // filterJSON must contain a JSON with this format: @@ -23,9 +27,9 @@ import "github.com/waku-org/go-waku/library" // (in milliseconds) is reached, or an error will be returned // //export waku_legacy_filter_subscribe -func waku_legacy_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_legacy_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.LegacyFilterSubscribe(C.GoString(filterJSON), C.GoString(peerID), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } // Removes subscriptions in a light node matching a content filter and, optionally, a pubSub topic. @@ -44,7 +48,7 @@ func waku_legacy_filter_subscribe(filterJSON *C.char, peerID *C.char, ms C.int, // (in milliseconds) is reached, or an error will be returned // //export waku_legacy_filter_unsubscribe -func waku_legacy_filter_unsubscribe(filterJSON *C.char, ms C.int, onErrCb C.WakuCallBack) C.int { +func waku_legacy_filter_unsubscribe(filterJSON *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { err := library.LegacyFilterUnsubscribe(C.GoString(filterJSON), int(ms)) - return execErrCB(onErrCb, err) + return onError(err, cb, userData) } diff --git a/library/c/api_lightpush.go b/library/c/api_lightpush.go index 83ca5760..909d62f8 100644 --- a/library/c/api_lightpush.go +++ b/library/c/api_lightpush.go @@ -4,7 +4,11 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Publish a message using waku lightpush. Use NULL for topic to derive the pubsub topic from the contentTopic. // peerID should contain the ID of a peer supporting the lightpush protocol. Use NULL to automatically select a node @@ -12,8 +16,8 @@ import "github.com/waku-org/go-waku/library" // (in milliseconds) is reached, or an error will be returned // //export waku_lightpush_publish -func waku_lightpush_publish(messageJSON *C.char, topic *C.char, peerID *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_lightpush_publish(messageJSON *C.char, topic *C.char, peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.LightpushPublish(C.GoString(messageJSON), C.GoString(topic), C.GoString(peerID), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } diff --git a/library/c/api_relay.go b/library/c/api_relay.go index 0f84c3ce..2b88af30 100644 --- a/library/c/api_relay.go +++ b/library/c/api_relay.go @@ -4,58 +4,74 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Determine if there are enough peers to publish a message on a topic. Use NULL // to verify the number of peers in the default pubsub topic // //export waku_relay_enough_peers -func waku_relay_enough_peers(topic *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_relay_enough_peers(topic *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { result, err := library.RelayEnoughPeers(C.GoString(topic)) if result { return "true", err } return "false", err - }, onOkCb, onErrCb) + }, cb, userData) } -// Publish a message using waku relay and returns the message ID. Use NULL for topic to use the default pubsub topic +// Publish a message using waku relay and returns the message ID. Use NULL for topic to derive the pubsub topic from the contentTopic. // If ms is greater than 0, the broadcast of the message must happen before the timeout // (in milliseconds) is reached, or an error will be returned. // //export waku_relay_publish -func waku_relay_publish(messageJSON *C.char, topic *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_relay_publish(messageJSON *C.char, topic *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.RelayPublish(C.GoString(messageJSON), C.GoString(topic), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } -// Subscribe to a WakuRelay topic. Set the topic to NULL to subscribe -// to the default topic. Returns a json response. When a message is received, -// a "message" event is emitted containing the message and pubsub topic in which +// Subscribe to WakuRelay to receive messages matching a content filter. +// filterJSON must contain a JSON with this format: +// +// { +// "pubsubTopic": "the pubsub topic" // optional if using autosharding, mandatory if using static or named sharding. +// "contentTopics": ["the content topic"] // optional +// } +// +// When a message is received, a "message" event is emitted containing the message and pubsub topic in which // the message was received // //export waku_relay_subscribe -func waku_relay_subscribe(topic *C.char, onErrCb C.WakuCallBack) C.int { - err := library.RelaySubscribe(C.GoString(topic)) - return execErrCB(onErrCb, err) +func waku_relay_subscribe(filterJSON *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { + err := library.RelaySubscribe(C.GoString(filterJSON)) + return onError(err, cb, userData) } // Returns a json response with the list of pubsub topics the node // is subscribed to in WakuRelay // //export waku_relay_topics -func waku_relay_topics(onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_relay_topics(cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.RelayTopics() - }, onOkCb, onErrCb) + }, cb, userData) } -// Closes the pubsub subscription to a pubsub topic +// Closes the pubsub subscription to stop receiving messages matching a content filter +// filterJSON must contain a JSON with this format: +// +// { +// "pubsubTopic": "the pubsub topic" // optional if using autosharding, mandatory if using static or named sharding. +// "contentTopics": ["the content topic"] // optional +// } // //export waku_relay_unsubscribe -func waku_relay_unsubscribe(topic *C.char, onErrCb C.WakuCallBack) C.int { - err := library.RelayUnsubscribe(C.GoString(topic)) - return execErrCB(onErrCb, err) +func waku_relay_unsubscribe(filterJSON *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { + err := library.RelayUnsubscribe(C.GoString(filterJSON)) + return onError(err, cb, userData) } diff --git a/library/c/api_store.go b/library/c/api_store.go index 7cf83cc4..f9e82ff4 100644 --- a/library/c/api_store.go +++ b/library/c/api_store.go @@ -4,30 +4,33 @@ package main #include */ import "C" -import "github.com/waku-org/go-waku/library" +import ( + "unsafe" + + "github.com/waku-org/go-waku/library" +) // Query historic messages using waku store protocol. // queryJSON must contain a valid json string with the following format: // // { // "pubsubTopic": "...", // optional string -// "startTime": 1234, // optional, unix epoch time in nanoseconds -// "endTime": 1234, // optional, unix epoch time in nanoseconds -// "contentFilters": [ // optional -// { -// contentTopic: "contentTopic1" -// }, ... -// ], -// "pagingOptions": {// optional pagination information -// "pageSize": 40, // number +// "startTime": 1234, // optional, unix epoch time in nanoseconds +// "endTime": 1234, // optional, unix epoch time in nanoseconds +// "contentTopics": [ // optional +// "contentTopic1", +// ... +// ], +// "pagingOptions": {// optional pagination information +// "pageSize": 40, // number // "cursor": { // optional // "digest": ..., // "receiverTime": ..., // "senderTime": ..., -// "pubsubTopic" ..., -// } +// "pubsubTopic": ..., +// }, // "forward": true, // sort order -// } +// } // } // // If a non empty cursor is returned, this function should be executed again, setting the `cursor` attribute with the cursor returned in the response @@ -36,10 +39,10 @@ import "github.com/waku-org/go-waku/library" // (in milliseconds) is reached, or an error will be returned // //export waku_store_query -func waku_store_query(queryJSON *C.char, peerID *C.char, ms C.int, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_store_query(queryJSON *C.char, peerID *C.char, ms C.int, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.StoreQuery(C.GoString(queryJSON), C.GoString(peerID), int(ms)) - }, onOkCb, onErrCb) + }, cb, userData) } // Query historic messages stored in the localDB using waku store protocol. @@ -47,31 +50,30 @@ func waku_store_query(queryJSON *C.char, peerID *C.char, ms C.int, onOkCb C.Waku // // { // "pubsubTopic": "...", // optional string -// "startTime": 1234, // optional, unix epoch time in nanoseconds -// "endTime": 1234, // optional, unix epoch time in nanoseconds -// "contentFilters": [ // optional -// { -// contentTopic: "contentTopic1" -// }, ... -// ], -// "pagingOptions": {// optional pagination information -// "pageSize": 40, // number +// "startTime": 1234, // optional, unix epoch time in nanoseconds +// "endTime": 1234, // optional, unix epoch time in nanoseconds +// "contentTopics": [ // optional +// "contentTopic1" +// ... +// ], +// "pagingOptions": {// optional pagination information +// "pageSize": 40, // number // "cursor": { // optional // "digest": ..., // "receiverTime": ..., // "senderTime": ..., -// "pubsubTopic" ..., -// } +// "pubsubTopic": ..., +// }, // "forward": true, // sort order -// } +// } // } // // If a non empty cursor is returned, this function should be executed again, setting the `cursor` attribute with the cursor returned in the response // Requires the `store` option to be passed when setting up the initial configuration // //export waku_store_local_query -func waku_store_local_query(queryJSON *C.char, onOkCb C.WakuCallBack, onErrCb C.WakuCallBack) C.int { +func waku_store_local_query(queryJSON *C.char, cb C.WakuCallBack, userData unsafe.Pointer) C.int { return singleFnExec(func() (string, error) { return library.StoreLocalQuery(C.GoString(queryJSON)) - }, onOkCb, onErrCb) + }, cb, userData) } diff --git a/library/c/cgo_utils.c b/library/c/cgo_utils.c index defe95f1..c28bf2cc 100644 --- a/library/c/cgo_utils.c +++ b/library/c/cgo_utils.c @@ -4,6 +4,6 @@ // This is a bridge function to execute C callbacks. // It's used internally in go-waku. Do not call directly -void _waku_execCB(WakuCallBack op, char* a, size_t b) { - op(a, b); +void _waku_execCB(WakuCallBack op, int retCode, char* msg, void * user_data) { + op(retCode, msg, user_data); } diff --git a/library/c/cgo_utils.go b/library/c/cgo_utils.go index 417e830f..120fd1d3 100644 --- a/library/c/cgo_utils.go +++ b/library/c/cgo_utils.go @@ -3,35 +3,51 @@ package main /* #include #include -extern void _waku_execCB(WakuCallBack op, char* a, size_t b); +extern void _waku_execCB(WakuCallBack cb, int retCode, char* msg, void* user_data); */ import "C" -import "unsafe" +import ( + "errors" + "unsafe" +) -func execOkCB(onOkCb C.WakuCallBack, value string) C.int { - if onOkCb == nil { - return retMissingCallback +const ret_ok = 0 +const ret_err = 1 +const ret_cb = 2 + +var errMissingCallback = errors.New("missing callback") + +func onSuccesfulResponse(value string, cb C.WakuCallBack, userData unsafe.Pointer) C.int { + retCode := ret_ok + if cb == nil { + retCode = ret_cb + value = errMissingCallback.Error() } - val := C.CString(value) - valLen := C.size_t(len(value)) - C._waku_execCB(onOkCb, val, valLen) + cstrVal := C.CString(value) + C._waku_execCB(cb, C.int(retCode), cstrVal, userData) - C.free(unsafe.Pointer(val)) + C.free(unsafe.Pointer(cstrVal)) - return retOk + return ret_ok } -func execErrCB(onErrCb C.WakuCallBack, err error) C.int { - if onErrCb == nil { - return retMissingCallback +func onError(err error, cb C.WakuCallBack, userData unsafe.Pointer) C.int { + retCode := ret_err + if cb == nil { + retCode = ret_cb + err = errMissingCallback } if err != nil { errMsg := err.Error() - execOkCB(onErrCb, errMsg) // reusing ok cb - return retErr + cstrVal := C.CString(errMsg) + C._waku_execCB(cb, C.int(retCode), cstrVal, userData) + C.free(unsafe.Pointer(cstrVal)) + return ret_err } - return retOk + retCode = ret_ok + C._waku_execCB(cb, C.int(retCode), nil, userData) + return ret_ok } diff --git a/library/c/cgo_utils.h b/library/c/cgo_utils.h index 47582ed2..ee017bec 100644 --- a/library/c/cgo_utils.h +++ b/library/c/cgo_utils.h @@ -1,6 +1,4 @@ #include #include -typedef void (*WakuCallBack) (const char* msg, size_t len_0); - -typedef void (*BytesCallBack) (uint8_t* data, size_t len_0); \ No newline at end of file +typedef void (*WakuCallBack) (int ret_code, const char* msg, void * user_data); diff --git a/library/encoding.go b/library/encoding.go index eefa54b4..e95fc1ca 100644 --- a/library/encoding.go +++ b/library/encoding.go @@ -128,6 +128,18 @@ func extractPubKeyAndSignature(payload *payload.DecodedPayload) (pubkey string, return } +type v0Response struct { + Data []byte `json:"data"` + Padding []byte `json:"padding"` +} + +type v1Response struct { + PubKey string `json:"pubkey,omitempty"` + Signature string `json:"signature,omitempty"` + Data []byte `json:"data"` + Padding []byte `json:"padding"` +} + // DecodeSymmetric decodes a waku message using a 32 bytes symmetric key. The key must be a hex encoded string with "0x" prefix func DecodeSymmetric(messageJSON string, symmetricKey string) (string, error) { var msg pb.WakuMessage @@ -137,7 +149,9 @@ func DecodeSymmetric(messageJSON string, symmetricKey string) (string, error) { } if msg.Version == 0 { - return marshalJSON(msg.Payload) + return marshalJSON(v0Response{ + Data: msg.Payload, + }) } else if msg.Version > 1 { return "", errors.New("unsupported wakumessage version") } @@ -158,12 +172,7 @@ func DecodeSymmetric(messageJSON string, symmetricKey string) (string, error) { pubkey, signature := extractPubKeyAndSignature(payload) - response := struct { - PubKey string `json:"pubkey,omitempty"` - Signature string `json:"signature,omitempty"` - Data []byte `json:"data"` - Padding []byte `json:"padding"` - }{ + response := v1Response{ PubKey: pubkey, Signature: signature, Data: payload.Data, @@ -182,7 +191,9 @@ func DecodeAsymmetric(messageJSON string, privateKey string) (string, error) { } if msg.Version == 0 { - return marshalJSON(msg.Payload) + return marshalJSON(v0Response{ + Data: msg.Payload, + }) } else if msg.Version > 1 { return "", errors.New("unsupported wakumessage version") } @@ -208,12 +219,7 @@ func DecodeAsymmetric(messageJSON string, privateKey string) (string, error) { pubkey, signature := extractPubKeyAndSignature(payload) - response := struct { - PubKey string `json:"pubkey,omitempty"` - Signature string `json:"signature,omitempty"` - Data []byte `json:"data"` - Padding []byte `json:"padding"` - }{ + response := v1Response{ PubKey: pubkey, Signature: signature, Data: payload.Data, diff --git a/library/filter.go b/library/filter.go index 687eb605..68e4d61c 100644 --- a/library/filter.go +++ b/library/filter.go @@ -81,7 +81,10 @@ func FilterSubscribe(filterJSON string, peerID string, ms int) (string, error) { } var subResult subscribeResult subResult.Subscriptions = subscriptions - subResult.Error = err.Error() + if err != nil { + subResult.Error = err.Error() + } + return marshalJSON(subResult) } diff --git a/library/lightpush.go b/library/lightpush.go index def0d47c..16389a1f 100644 --- a/library/lightpush.go +++ b/library/lightpush.go @@ -52,5 +52,5 @@ func LightpushPublish(messageJSON string, pubsubTopic string, peerID string, ms return "", err } - return lightpushPublish(msg, getTopic(pubsubTopic), peerID, ms) + return lightpushPublish(msg, pubsubTopic, peerID, ms) } diff --git a/library/node.go b/library/node.go index a3da4f03..2b3b9393 100644 --- a/library/node.go +++ b/library/node.go @@ -265,7 +265,7 @@ func AddPeer(address string, protocolID string) (string, error) { return "", err } - return marshalJSON(peerID) + return peerID.String(), nil } // Connect is used to connect to a peer at multiaddress. if ms > 0, cancel the function execution if it takes longer than N milliseconds @@ -350,13 +350,6 @@ func DefaultPubsubTopic() string { return protocol.DefaultPubsubTopic().String() } -func getTopic(topic string) string { - if topic == "" { - return protocol.DefaultPubsubTopic().String() - } - return topic -} - type subscriptionMsg struct { MessageID string `json:"messageId"` PubsubTopic string `json:"pubsubTopic"` @@ -382,5 +375,18 @@ func Peers() (string, error) { return "", err } + for _, p := range peers { + addrs := []multiaddr.Multiaddr{} + for i := range p.Addrs { + // Filtering out SNI addresses due to https://github.com/waku-org/waku-rust-bindings/issues/66 + // TODO: once https://github.com/multiformats/rust-multiaddr/issues/88 is implemented, remove this + _, err := p.Addrs[i].ValueForProtocol(multiaddr.P_SNI) + if err != nil { + addrs = append(addrs, p.Addrs[i]) + } + } + p.Addrs = addrs + } + return marshalJSON(peers) } diff --git a/library/relay.go b/library/relay.go index e77c49d5..fa2d4c1e 100644 --- a/library/relay.go +++ b/library/relay.go @@ -4,17 +4,12 @@ import ( "context" "time" - "sync" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/waku-org/go-waku/waku/v2/protocol" "github.com/waku-org/go-waku/waku/v2/protocol/pb" "github.com/waku-org/go-waku/waku/v2/protocol/relay" ) -var relaySubscriptions map[string]*relay.Subscription = make(map[string]*relay.Subscription) -var relaySubsMutex sync.Mutex - // RelayEnoughPeers determines if there are enough peers to publish a message on a topic func RelayEnoughPeers(topic string) (bool, error) { if wakuState.node == nil { @@ -55,43 +50,38 @@ func RelayPublish(messageJSON string, topic string, ms int) (string, error) { return "", err } - return relayPublish(msg, getTopic(topic), int(ms)) + return relayPublish(msg, topic, int(ms)) } -func relaySubscribe(topic string) error { - topicToSubscribe := getTopic(topic) - - relaySubsMutex.Lock() - defer relaySubsMutex.Unlock() - - _, ok := relaySubscriptions[topicToSubscribe] - if ok { - return nil - } - - subscription, err := wakuState.node.Relay().Subscribe(context.Background(), protocol.NewContentFilter(topicToSubscribe)) +func relaySubscribe(filterJSON string) error { + cf, err := toContentFilter(filterJSON) if err != nil { return err } - relaySubscriptions[topicToSubscribe] = subscription[0] + subscriptions, err := wakuState.node.Relay().Subscribe(context.Background(), cf) + if err != nil { + return err + } - go func(subscription *relay.Subscription) { - for envelope := range subscription.Ch { - send("message", toSubscriptionMessage(envelope)) - } - }(subscription[0]) + for _, sub := range subscriptions { + go func(subscription *relay.Subscription) { + for envelope := range subscription.Ch { + send("message", toSubscriptionMessage(envelope)) + } + }(sub) + } return nil } // RelaySubscribe subscribes to a WakuRelay topic. -func RelaySubscribe(topic string) error { +func RelaySubscribe(contentFilterJSON string) error { if wakuState.node == nil { return errWakuNodeNotReady } - return relaySubscribe(topic) + return relaySubscribe(contentFilterJSON) } // RelayTopics returns a list of pubsub topics the node is subscribed to in WakuRelay @@ -104,24 +94,15 @@ func RelayTopics() (string, error) { } // RelayUnsubscribe closes the pubsub subscription to a pubsub topic -func RelayUnsubscribe(topic string) error { +func RelayUnsubscribe(contentFilterJSON string) error { + cf, err := toContentFilter(contentFilterJSON) + if err != nil { + return err + } + if wakuState.node == nil { return errWakuNodeNotReady } - topicToUnsubscribe := getTopic(topic) - - relaySubsMutex.Lock() - defer relaySubsMutex.Unlock() - - subscription, ok := relaySubscriptions[topicToUnsubscribe] - if ok { - return nil - } - - subscription.Unsubscribe() - - delete(relaySubscriptions, topicToUnsubscribe) - - return wakuState.node.Relay().Unsubscribe(context.Background(), protocol.NewContentFilter(topicToUnsubscribe)) + return wakuState.node.Relay().Unsubscribe(context.Background(), cf) } diff --git a/library/signals.c b/library/signals.c index 8733fbc5..6756a562 100644 --- a/library/signals.c +++ b/library/signals.c @@ -7,12 +7,12 @@ #include #include "_cgo_export.h" -typedef void (*callback)(const char *jsonEvent, size_t len_0); +typedef void (*callback)(int retCode, const char *jsonEvent, void* userData); callback gCallback = 0; -bool ServiceSignalEvent(const char *jsonEvent, size_t len_0) { +bool ServiceSignalEvent(const char *jsonEvent) { if (gCallback) { - gCallback(jsonEvent, len_0); + gCallback(0, jsonEvent, NULL); } return true; diff --git a/library/signals.go b/library/signals.go index 7aebb017..514872aa 100644 --- a/library/signals.go +++ b/library/signals.go @@ -4,7 +4,7 @@ package library #include #include #include -extern bool ServiceSignalEvent(const char *jsonEvent, size_t len); +extern bool ServiceSignalEvent(const char *jsonEvent); extern void SetEventCallback(void *cb); */ import "C" @@ -51,7 +51,7 @@ func send(signalType string, event interface{}) { // ...and fallback to C implementation otherwise. dataStr := string(data) str := C.CString(dataStr) - C.ServiceSignalEvent(str, C.size_t(len(data))) + C.ServiceSignalEvent(str) C.free(unsafe.Pointer(str)) } } diff --git a/library/store.go b/library/store.go index 0dbfe29a..837e1072 100644 --- a/library/store.go +++ b/library/store.go @@ -22,11 +22,11 @@ type storePagingOptions struct { } type storeMessagesArgs struct { - Topic string `json:"pubsubTopic,omitempty"` - ContentFilters []*pb.ContentFilter `json:"contentFilters,omitempty"` - StartTime int64 `json:"startTime,omitempty"` - EndTime int64 `json:"endTime,omitempty"` - PagingOptions storePagingOptions `json:"pagingOptions,omitempty"` + Topic string `json:"pubsubTopic,omitempty"` + ContentTopics []string `json:"contentTopics,omitempty"` + StartTime int64 `json:"startTime,omitempty"` + EndTime int64 `json:"endTime,omitempty"` + PagingOptions storePagingOptions `json:"pagingOptions,omitempty"` } type storeMessagesReply struct { @@ -36,16 +36,11 @@ type storeMessagesReply struct { } func queryResponse(ctx context.Context, args storeMessagesArgs, options []store.HistoryRequestOption) (string, error) { - var contentTopics []string - for _, ct := range args.ContentFilters { - contentTopics = append(contentTopics, ct.ContentTopic) - } - res, err := wakuState.node.Store().Query( ctx, store.Query{ Topic: args.Topic, - ContentTopics: contentTopics, + ContentTopics: args.ContentTopics, StartTime: args.StartTime, EndTime: args.EndTime, }, diff --git a/waku/v2/protocol/content_filter.go b/waku/v2/protocol/content_filter.go index ef9e1bdf..795e3ff6 100644 --- a/waku/v2/protocol/content_filter.go +++ b/waku/v2/protocol/content_filter.go @@ -20,8 +20,8 @@ func NewContentTopicSet(contentTopics ...string) ContentTopicSet { // ContentTopics - Specify list of content topics to be filtered under a pubSubTopic (for named and static sharding), or a list of contentTopics (in case ofAuto sharding) // If pubSub topic is not specified, then content-topics are used to derive the shard and corresponding pubSubTopic using autosharding algorithm type ContentFilter struct { - PubsubTopic string - ContentTopics ContentTopicSet + PubsubTopic string `json:"pubsubTopic"` + ContentTopics ContentTopicSet `json:"contentTopics"` } func (cf ContentFilter) ContentTopicsList() []string { diff --git a/waku/v2/protocol/subscription/subscriptions_map.go b/waku/v2/protocol/subscription/subscriptions_map.go index 6239e18b..92f57e2d 100644 --- a/waku/v2/protocol/subscription/subscriptions_map.go +++ b/waku/v2/protocol/subscription/subscriptions_map.go @@ -15,14 +15,14 @@ import ( type SubscriptionDetails struct { sync.RWMutex - ID string + ID string `json:"subscriptionID"` mapRef *SubscriptionsMap - Closed bool + Closed bool `json:"-"` once sync.Once - PeerID peer.ID - ContentFilter protocol.ContentFilter - C chan *protocol.Envelope + PeerID peer.ID `json:"peerID"` + ContentFilter protocol.ContentFilter `json:"contentFilters"` + C chan *protocol.Envelope `json:"-"` } // Map of SubscriptionDetails.ID to subscriptions