From 3869006dd6b926c28e4781fcbae775bc6926fda2 Mon Sep 17 00:00:00 2001 From: Serhii Mamontov Date: Thu, 14 Nov 2024 16:49:55 +0200 Subject: [PATCH] feat(message-type): add custom message type support Add custom message type support for the following APIs: publish, signal, share file, subscribe and history. --- core/pbcc_fetch_history.c | 4 +- core/pbcc_fetch_history.h | 1 + core/pbcc_subscribe_v2.c | 7 +++- core/pbcc_subscribe_v2.h | 2 +- core/pubnub_ccore_pubsub.c | 12 +++++- core/pubnub_ccore_pubsub.h | 6 ++- core/pubnub_coreapi_ex.c | 48 +++++++++++++++++++--- core/pubnub_coreapi_ex.h | 41 +++++++++++++++++- core/pubnub_fetch_history.c | 2 + core/pubnub_fetch_history.h | 4 ++ core/pubnub_pubsubapi.c | 4 +- core/pubnub_subscribe_v2_message.h | 2 + core/samples/pubnub_fetch_history_sample.c | 14 ++++++- 13 files changed, 129 insertions(+), 18 deletions(-) diff --git a/core/pbcc_fetch_history.c b/core/pbcc_fetch_history.c index 24b45a65..20d417d6 100644 --- a/core/pbcc_fetch_history.c +++ b/core/pbcc_fetch_history.c @@ -21,6 +21,7 @@ enum pubnub_res pbcc_fetch_history_prep(struct pbcc_context* pb, const char* channel, unsigned int max_per_channel, enum pubnub_tribool include_meta, + enum pubnub_tribool include_custom_message_type, enum pubnub_tribool include_message_type, enum pubnub_tribool include_user_id, enum pubnub_tribool include_message_actions, @@ -59,7 +60,8 @@ enum pubnub_res pbcc_fetch_history_prep(struct pbcc_context* pb, if (max_per_channel) { ADD_URL_PARAM(qparam, max, max_per_ch_cnt_buf); } if (include_meta != pbccNotSet) { ADD_URL_PARAM(qparam, include_meta, include_meta == pbccTrue ? "true" : "false"); } - if (include_message_type != pbccNotSet) { ADD_URL_PARAM(qparam, include_message_type, include_meta == pbccTrue ? "true" : "false"); } + if (include_custom_message_type != pbccNotSet) { ADD_URL_PARAM(qparam, include_custom_message_type, include_custom_message_type == pbccTrue ? "true" : "false"); } + if (include_message_type != pbccNotSet) { ADD_URL_PARAM(qparam, include_message_type, include_message_type == pbccTrue ? "true" : "false"); } if (include_user_id != pbccNotSet) { ADD_URL_PARAM(qparam, include_uuid, include_user_id == pbccTrue ? "true" : "false"); } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } diff --git a/core/pbcc_fetch_history.h b/core/pbcc_fetch_history.h index c16739e4..d2072e77 100644 --- a/core/pbcc_fetch_history.h +++ b/core/pbcc_fetch_history.h @@ -10,6 +10,7 @@ enum pubnub_res pbcc_fetch_history_prep(struct pbcc_context* pb, const char* channel, unsigned int max_per_channel, enum pubnub_tribool include_meta, + enum pubnub_tribool include_custom_message_type, enum pubnub_tribool include_message_type, enum pubnub_tribool include_user_id, enum pubnub_tribool include_message_actions, diff --git a/core/pbcc_subscribe_v2.c b/core/pbcc_subscribe_v2.c index e1c50650..119bb749 100644 --- a/core/pbcc_subscribe_v2.c +++ b/core/pbcc_subscribe_v2.c @@ -27,7 +27,7 @@ enum pubnub_res pbcc_subscribe_v2_prep(struct pbcc_context* p, char const* channel, char const* channel_group, - unsigned* heartbeat, + const unsigned* heartbeat, char const* filter_expr) { char region_str[20]; @@ -303,6 +303,11 @@ struct pubnub_v2_message pbcc_get_msg_v2(struct pbcc_context* p) rslt.message_type = pbsbPublished; } + if (jonmpOK == pbjson_get_object_value(&el, "cmt", &found)) { + rslt.custom_message_type.ptr = (char*)found.start + 1; + rslt.custom_message_type.size = found.end - found.start - 2; + } + jpresult = pbjson_get_object_value(&el, "p", &found); if (jonmpOK == jpresult) { struct pbjson_elem titel; diff --git a/core/pbcc_subscribe_v2.h b/core/pbcc_subscribe_v2.h index 642f969a..cce9c340 100644 --- a/core/pbcc_subscribe_v2.h +++ b/core/pbcc_subscribe_v2.h @@ -15,7 +15,7 @@ struct pbcc_context; enum pubnub_res pbcc_subscribe_v2_prep(struct pbcc_context* p, char const* channel, char const* channel_group, - unsigned* heartbeat, + const unsigned* heartbeat, char const* filter_expr); diff --git a/core/pubnub_ccore_pubsub.c b/core/pubnub_ccore_pubsub.c index 6822467e..62d6026b 100644 --- a/core/pubnub_ccore_pubsub.c +++ b/core/pubnub_ccore_pubsub.c @@ -525,6 +525,7 @@ enum pubnub_res pbcc_append_url_param_encoded(struct pbcc_context* pb, enum pubnub_res pbcc_publish_prep(struct pbcc_context* pb, const char* channel, const char* message, + const char* custom_message_type, bool store_in_history, bool norep, char const* meta, @@ -606,6 +607,9 @@ enum pubnub_res pbcc_publish_prep(struct pbcc_context* pb, if (!store_in_history) { ADD_URL_PARAM(qparam, store, "0"); } if (norep) { ADD_URL_PARAM(qparam, norep, "true"); } if (meta) { ADD_URL_PARAM(qparam, meta, meta); } + if (custom_message_type) { + ADD_URL_PARAM(qparam, custom_message_type, custom_message_type); + } #if PUBNUB_CRYPTO_API SORT_URL_PARAMETERS(qparam); @@ -667,7 +671,8 @@ enum pubnub_res pbcc_sign_url(struct pbcc_context* pc, const char* msg, enum pub enum pubnub_res pbcc_signal_prep(struct pbcc_context* pb, const char* channel, - const char* message) + const char* message, + const char* custom_message_type) { enum pubnub_res rslt = PNR_OK; char const* const uname = pubnub_uname(); @@ -689,6 +694,9 @@ enum pubnub_res pbcc_signal_prep(struct pbcc_context* pb, URL_PARAMS_INIT(qparam, PUBNUB_MAX_URL_PARAMS); if (uname) { ADD_URL_PARAM(qparam, pnsdk, uname); } if (user_id) { ADD_URL_PARAM(qparam, uuid, user_id); } + if (custom_message_type) { + ADD_URL_PARAM(qparam, custom_message_type, custom_message_type); + } #if PUBNUB_CRYPTO_API if (pb->secret_key == NULL) { ADD_URL_AUTH_PARAM(pb, qparam, auth); } ADD_TS_TO_URL_PARAM(); @@ -716,7 +724,7 @@ enum pubnub_res pbcc_signal_prep(struct pbcc_context* pb, enum pubnub_res pbcc_subscribe_prep(struct pbcc_context* p, char const* channel, char const* channel_group, - unsigned* heartbeat) + const unsigned* heartbeat) { char const* user_id = pbcc_user_id_get(p); char const* const uname = pubnub_uname(); diff --git a/core/pubnub_ccore_pubsub.h b/core/pubnub_ccore_pubsub.h index 1e03e6a8..737cbfed 100644 --- a/core/pubnub_ccore_pubsub.h +++ b/core/pubnub_ccore_pubsub.h @@ -477,6 +477,7 @@ void pbcc_via_post_headers(struct pbcc_context* p, char* header, size_t max_leng enum pubnub_res pbcc_publish_prep(struct pbcc_context* pb, const char* channel, const char* message, + const char* custom_message_type, bool store_in_history, bool norep, char const* meta, @@ -488,7 +489,8 @@ enum pubnub_res pbcc_publish_prep(struct pbcc_context* pb, */ enum pubnub_res pbcc_signal_prep(struct pbcc_context* pb, const char* channel, - const char* message); + const char* message, + const char* custom_message_type); /** Prepares the Subscribe operation (transaction), mostly by formatting the URI of the HTTP request. @@ -496,7 +498,7 @@ enum pubnub_res pbcc_signal_prep(struct pbcc_context* pb, enum pubnub_res pbcc_subscribe_prep(struct pbcc_context* p, char const* channel, char const* channel_group, - unsigned* heartbeat); + const unsigned* heartbeat); /** Split @p buf string containing a JSON array (with arbitrary diff --git a/core/pubnub_coreapi_ex.c b/core/pubnub_coreapi_ex.c index 119a28c7..513f8284 100644 --- a/core/pubnub_coreapi_ex.c +++ b/core/pubnub_coreapi_ex.c @@ -27,12 +27,13 @@ struct pubnub_publish_options pubnub_publish_defopts(void) { struct pubnub_publish_options result; - result.store = true; - result.cipher_key = NULL; - result.replicate = true; - result.meta = NULL; - result.method = pubnubSendViaGET; - result.ttl = SIZE_MAX; + result.store = true; + result.cipher_key = NULL; + result.replicate = true; + result.meta = NULL; + result.method = pubnubSendViaGET; + result.ttl = SIZE_MAX; + result.custom_message_type = NULL; return result; } @@ -85,6 +86,7 @@ enum pubnub_res pubnub_publish_ex(pubnub_t* pb, rslt = pbcc_publish_prep(&pb->core, channel, message, + opts.custom_message_type, opts.store, !opts.replicate, opts.meta, @@ -102,6 +104,40 @@ enum pubnub_res pubnub_publish_ex(pubnub_t* pb, return rslt; } +struct pubnub_signal_options pubnub_signal_defopts(void) +{ + struct pubnub_signal_options result; + result.custom_message_type = NULL; + return result; +} + +enum pubnub_res pubnub_signal_ex( + pubnub_t* pb, + const char* channel, + const char* message, + struct pubnub_signal_options opts) +{ + enum pubnub_res rslt; + + PUBNUB_ASSERT(pb_valid_ctx_ptr(pb)); + + pubnub_mutex_lock(pb->monitor); + if (!pbnc_can_start_transaction(pb)) { + pubnub_mutex_unlock(pb->monitor); + return PNR_IN_PROGRESS; + } + + rslt = pbcc_signal_prep(&pb->core, channel, message, opts.custom_message_type); + if (PNR_STARTED == rslt) { + pb->trans = PBTT_SIGNAL; + pb->core.last_result = PNR_STARTED; + pbnc_fsm(pb); + rslt = pb->core.last_result; + } + pubnub_mutex_unlock(pb->monitor); + + return rslt; +} struct pubnub_subscribe_options pubnub_subscribe_defopts(void) { diff --git a/core/pubnub_coreapi_ex.h b/core/pubnub_coreapi_ex.h index 79a88b30..2b0a8b95 100644 --- a/core/pubnub_coreapi_ex.h +++ b/core/pubnub_coreapi_ex.h @@ -65,6 +65,11 @@ struct pubnub_publish_options { API. */ size_t ttl; + /** User-specified message type. + Important: String limited by **3**-**50** case-sensitive alphanumeric + characters with only `-` and `_` special characters allowed. + */ + char const* custom_message_type; }; /** This returns the default options for publish V1 transactions. @@ -85,7 +90,7 @@ PUBNUB_EXTERN struct pubnub_publish_options pubnub_publish_defopts(void); @param p The Pubnub context. Can't be NULL. @param channel The string with the channel name to publish to. Can't be NULL. - @param opt Publish V1 options + @param opts Publish V1 options @return #PNR_STARTED on success, an error otherwise */ PUBNUB_EXTERN enum pubnub_res pubnub_publish_ex(pubnub_t* p, @@ -94,6 +99,40 @@ PUBNUB_EXTERN enum pubnub_res pubnub_publish_ex(pubnub_t* p, struct pubnub_publish_options opts); +/** Options for "extended" signal V1. */ +struct pubnub_signal_options { + /** User-specified message type. + Important: String limited by **3**-**50** case-sensitive alphanumeric + characters with only `-` and `_` special characters allowed. + */ + char const* custom_message_type; +}; + +/** This returns the default options for signal V1 transactions. */ +PUBNUB_EXTERN struct pubnub_signal_options pubnub_signal_defopts(void); + +/** The extended signal V1. Basically the same as pubnub_signal(), + but with added optional parameters in @p opts. + + Basic usage: + + struct pubnub_signal_options opt = pubnub_signal_defopts(); + opt.custom_message_type = "test-message-type"; + pbresult = pubnub_signal_ex(pn, "my_channel", "status:active", opt); + + @param pb The pubnub context. Can't be NULL + @param channel The string with the channel to signal to. + @param message The signal message to send, expected to be in JSON format + @param opts Signal V1 options + @return #PNR_STARTED on success, an error otherwise +*/ +PUBNUB_EXTERN enum pubnub_res pubnub_signal_ex( + pubnub_t* pb, + const char* channel, + const char* message, + struct pubnub_signal_options opts); + + /** Options for "extended" subscribe. */ struct pubnub_subscribe_options { /** Channel group (a comma-delimited list of channel group names). diff --git a/core/pubnub_fetch_history.c b/core/pubnub_fetch_history.c index c4626190..85e729fa 100644 --- a/core/pubnub_fetch_history.c +++ b/core/pubnub_fetch_history.c @@ -23,6 +23,7 @@ struct pubnub_fetch_history_options pubnub_fetch_history_defopts(void) rslt.include_message_type = false; rslt.include_user_id = false; rslt.include_message_actions = false; + rslt.include_custom_message_type = false; return rslt; } @@ -45,6 +46,7 @@ enum pubnub_res pubnub_fetch_history(pubnub_t* pb, channel, opt.max_per_channel, opt.include_meta ? pbccTrue : pbccFalse, + opt.include_custom_message_type ? pbccTrue : pbccFalse, opt.include_message_type ? pbccTrue : pbccFalse, opt.include_user_id ? pbccTrue : pbccFalse, opt.include_message_actions ? pbccTrue : pbccFalse, diff --git a/core/pubnub_fetch_history.h b/core/pubnub_fetch_history.h index 45e92c42..2379a3d2 100644 --- a/core/pubnub_fetch_history.h +++ b/core/pubnub_fetch_history.h @@ -55,6 +55,10 @@ struct pubnub_fetch_history_options { * false. */ bool include_message_actions; + /** Include messages' custom type flag. + Message / signal and file messages may contain user-provided type. + */ + bool include_custom_message_type; }; /** This returns the default options for fetch history transactions. diff --git a/core/pubnub_pubsubapi.c b/core/pubnub_pubsubapi.c index ac9b027d..624dc0ef 100644 --- a/core/pubnub_pubsubapi.c +++ b/core/pubnub_pubsubapi.c @@ -110,7 +110,7 @@ enum pubnub_res pubnub_publish(pubnub_t* pb, const char* channel, const char* me } rslt = pbcc_publish_prep( - &pb->core, channel, message, true, false, NULL, SIZE_MAX, pubnubSendViaGET); + &pb->core, channel, message, NULL, true, false, NULL, SIZE_MAX, pubnubSendViaGET); if (PNR_STARTED == rslt) { pb->trans = PBTT_PUBLISH; pb->core.last_result = PNR_STARTED; @@ -137,7 +137,7 @@ enum pubnub_res pubnub_signal(pubnub_t* pb, return PNR_IN_PROGRESS; } - rslt = pbcc_signal_prep(&pb->core, channel, message); + rslt = pbcc_signal_prep(&pb->core, channel, message, NULL); if (PNR_STARTED == rslt) { pb->trans = PBTT_SIGNAL; pb->core.last_result = PNR_STARTED; diff --git a/core/pubnub_subscribe_v2_message.h b/core/pubnub_subscribe_v2_message.h index bd02cbfb..4c712418 100644 --- a/core/pubnub_subscribe_v2_message.h +++ b/core/pubnub_subscribe_v2_message.h @@ -54,6 +54,8 @@ struct pubnub_v2_message { enum pubnub_message_type message_type; /** The message information about publisher */ struct pubnub_char_mem_block publisher; + /** User-provided message type. */ + struct pubnub_char_mem_block custom_message_type; }; diff --git a/core/samples/pubnub_fetch_history_sample.c b/core/samples/pubnub_fetch_history_sample.c index 03e19fd3..8cfb62b4 100644 --- a/core/samples/pubnub_fetch_history_sample.c +++ b/core/samples/pubnub_fetch_history_sample.c @@ -4,6 +4,7 @@ #if PUBNUB_USE_FETCH_HISTORY #include "core/pubnub_fetch_history.c" #endif +#include "core/pubnub_coreapi_ex.h" #include "core/pubnub_helper.h" #include "core/pubnub_timers.h" @@ -58,9 +59,13 @@ static void publish_on_channels(pubnub_t* pbp) enum pubnub_res res; char msg[100]; sprintf(msg,"\"Hello world from fetch history sample %d !\"", i); - res = pubnub_publish(pbp, + struct pubnub_publish_options opts = pubnub_publish_defopts(); + opts.custom_message_type = "test-message-type"; + + res = pubnub_publish_ex(pbp, m_channel1, - msg); + msg, + opts); if (res == PNR_STARTED) { puts("Await publish"); res = pubnub_await(pbp); @@ -139,6 +144,7 @@ int main(int argc, char* argv[]) m_channel2); struct pubnub_fetch_history_options opt = pubnub_fetch_history_defopts(); + opt.include_custom_message_type = true; opt.include_message_type = true; opt.include_meta = true; res = pubnub_fetch_history(pbp, string_channels, opt); @@ -162,6 +168,10 @@ int main(int argc, char* argv[]) printf("\"meta\" is missing in response."); return 1; } + if (NULL == strstr(response.ptr, "\"custom_message_type\"")) { + printf("\"custom_message_type\" is missing in response."); + return 1; + } } else{ printf("pubnub_fetch_history() failed with code: %d('%s')\n",