From 014e03c72e691ff701dccc8c46fb74873419afbe Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Mon, 10 Aug 2020 15:23:30 +0200 Subject: [PATCH 1/8] Start working on MAM RSM to get more pages Regards https://github.com/profanity-im/profanity/issues/660 --- src/xmpp/iq.c | 25 ++++++++++++++++++++++++- src/xmpp/stanza.h | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index d1797a72..56659c1a 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -142,6 +142,7 @@ static int _auto_pong_id_handler(xmpp_stanza_t* const stanza, void* const userda static int _room_list_id_handler(xmpp_stanza_t* const stanza, void* const userdata); static int _command_list_result_handler(xmpp_stanza_t* const stanza, void* const userdata); static int _command_exec_response_handler(xmpp_stanza_t* const stanza, void* const userdata); +static int _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata); static void _iq_free_room_data(ProfRoomInfoData* roominfo); static void _iq_free_affiliation_set(ProfPrivilegeSet* affiliation_set); @@ -2559,7 +2560,7 @@ iq_mam_request(ProfChatWin* win) g_free(datestr); g_date_time_unref(timestamp); - // iq_id_handler_add(id, _http_upload_response_id_handler, NULL, upload); + iq_id_handler_add(id, _mam_rsm_id_handler, NULL, NULL); free(id); iq_send_stanza(iq); @@ -2567,3 +2568,25 @@ iq_mam_request(ProfChatWin* win) return; } + +static int +_mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) +{ + const char* type = xmpp_stanza_get_type(stanza); + if (g_strcmp0(type, "error") == 0) { + //TODO + //char* error_message = stanza_get_error_message(stanza); + } else if (g_strcmp0(type, "result") == 0) { + xmpp_stanza_t* fin = stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2); + if (fin) { + xmpp_stanza_t* set = stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); + if (set) { + xmpp_stanza_t* last = xmpp_stanza_get_child_by_name(set, STANZA_NAME_LAST); + char* lastid = xmpp_stanza_get_text(last); + lastid = lastid; + } + } + } + + return 0; +} diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 95cdc29b..f57a6d22 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -113,6 +113,8 @@ #define STANZA_NAME_STANZA_ID "stanza-id" #define STANZA_NAME_RESULT "result" #define STANZA_NAME_MINIMIZE "minimize" +#define STANZA_NAME_FIN "fin" +#define STANZA_NAME_LAST "last" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -220,6 +222,7 @@ #define STANZA_NS_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0" #define STANZA_NS_MAM2 "urn:xmpp:mam:2" #define STANZA_NS_EXT_GAJIM_BOOKMARKS "xmpp:gajim.org/bookmarks" +#define STANZA_NS_RSM "http://jabber.org/protocol/rsm" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" From d06ca640989070c364fde882b031df17765f88e6 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 28 Oct 2020 13:13:31 +0100 Subject: [PATCH 2/8] mam: fix logging message --- src/xmpp/iq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 56659c1a..7248bbd4 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2544,7 +2544,7 @@ void iq_mam_request(ProfChatWin* win) { if (connection_supports(XMPP_FEATURE_MAM2) == FALSE) { - log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_PING); + log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_MAM2); cons_show_error("Server doesn't support MAM."); return; } From 69e35e86b206e8c887907c84da4e32a01cedab04 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 28 Oct 2020 14:21:37 +0100 Subject: [PATCH 3/8] mam: Use correct ID in rsm handler Thanks to DebXWoody for the help. --- src/xmpp/iq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 7248bbd4..4e7aec4a 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2550,7 +2550,6 @@ iq_mam_request(ProfChatWin* win) } xmpp_ctx_t* const ctx = connection_get_ctx(); - char* id = connection_create_stanza_id(); GDateTime* now = g_date_time_new_now_utc(); GDateTime* timestamp = g_date_time_add_days(now, -1); @@ -2560,8 +2559,7 @@ iq_mam_request(ProfChatWin* win) g_free(datestr); g_date_time_unref(timestamp); - iq_id_handler_add(id, _mam_rsm_id_handler, NULL, NULL); - free(id); + iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, NULL); iq_send_stanza(iq); xmpp_stanza_release(iq); From db65255a5a3c39dd7ad70b45c3610ec4fb02aac8 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 28 Oct 2020 15:57:53 +0100 Subject: [PATCH 4/8] wip: add rsm after we get the first couple of mam messages --- src/xmpp/iq.c | 21 ++++++++++++++++++--- src/xmpp/stanza.c | 27 ++++++++++++++++++++++++++- src/xmpp/stanza.h | 3 ++- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index 4e7aec4a..f1665616 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2556,11 +2556,12 @@ iq_mam_request(ProfChatWin* win) g_date_time_unref(now); gchar* datestr = g_date_time_format(timestamp, "%FT%TZ"); xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr); + + iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, g_strdup(datestr)); + g_free(datestr); g_date_time_unref(timestamp); - iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, NULL); - iq_send_stanza(iq); xmpp_stanza_release(iq); @@ -2573,7 +2574,12 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, "error") == 0) { //TODO - //char* error_message = stanza_get_error_message(stanza); + /* + char* error_message = stanza_get_error_message(stanza); + cons_show_error("Server error: %s", error_message); + log_debug("Error: %s", error_message); + free(error_message); + */ } else if (g_strcmp0(type, "result") == 0) { xmpp_stanza_t* fin = stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2); if (fin) { @@ -2582,6 +2588,15 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) xmpp_stanza_t* last = xmpp_stanza_get_child_by_name(set, STANZA_NAME_LAST); char* lastid = xmpp_stanza_get_text(last); lastid = lastid; + + // 4.3.2. send same stanza with set,max stanza + xmpp_ctx_t* const ctx = connection_get_ctx(); + gchar *datestr = (gchar*)userdata; + //TODO give barejid or get from stanza + xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, NULL, datestr, lastid); + + iq_send_stanza(iq); + xmpp_stanza_release(iq); } } } diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index fbbbfc9c..06615aa9 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -2615,7 +2615,7 @@ stanza_attach_correction(xmpp_ctx_t* ctx, xmpp_stanza_t* stanza, const char* con } xmpp_stanza_t* -stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate) +stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char *const lastid) { char* id = connection_create_stanza_id(); xmpp_stanza_t* iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); @@ -2674,6 +2674,23 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s xmpp_stanza_add_child(field_start, value_start); + // 4.3.2 set/rsm + xmpp_stanza_t *after, *after_text, *set; + if (lastid) { + set = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(set, STANZA_TYPE_SET); + xmpp_stanza_set_ns(set, STANZA_NS_RSM); + + after = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(after, STANZA_NAME_AFTER); + + after_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(after_text, lastid); + + xmpp_stanza_add_child(after, after_text); + xmpp_stanza_add_child(set, after); + } + // add and release xmpp_stanza_add_child(iq, query); xmpp_stanza_add_child(query, x); @@ -2681,6 +2698,14 @@ stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const s xmpp_stanza_add_child(x, field_with); xmpp_stanza_add_child(x, field_start); + if (lastid) { + xmpp_stanza_add_child(query, after); + + xmpp_stanza_release(after_text); + xmpp_stanza_release(after); + xmpp_stanza_release(set); + } + xmpp_stanza_release(mam_text); xmpp_stanza_release(with_text); xmpp_stanza_release(date_text); diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index f57a6d22..e35b4bcc 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -115,6 +115,7 @@ #define STANZA_NAME_MINIMIZE "minimize" #define STANZA_NAME_FIN "fin" #define STANZA_NAME_LAST "last" +#define STANZA_NAME_AFTER "after" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -380,6 +381,6 @@ void stanza_free_caps(XMPPCaps* caps); xmpp_stanza_t* stanza_create_avatar_retrieve_data_request(xmpp_ctx_t* ctx, const char* stanza_id, const char* const item_id, const char* const jid); -xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate); +xmpp_stanza_t* stanza_create_mam_iq(xmpp_ctx_t* ctx, const char* const jid, const char* const startdate, const char *const lastid); #endif From 6e1e01dbb8476899efdd3d4a169f821c8e388ad5 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Thu, 28 Jan 2021 13:55:47 +0100 Subject: [PATCH 5/8] Adapt MAM RSM code to latest functions Some functions changed in the meantime. stanza_get_child_by_name_and_ns() got dropped and xmpp_stanza_get_child_by_name_and_ns() from newer libstrophe is used. --- src/xmpp/iq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index f1665616..e7648251 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2555,7 +2555,7 @@ iq_mam_request(ProfChatWin* win) GDateTime* timestamp = g_date_time_add_days(now, -1); g_date_time_unref(now); gchar* datestr = g_date_time_format(timestamp, "%FT%TZ"); - xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr); + xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr, NULL); iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, g_strdup(datestr)); @@ -2581,9 +2581,9 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) free(error_message); */ } else if (g_strcmp0(type, "result") == 0) { - xmpp_stanza_t* fin = stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2); + xmpp_stanza_t* fin = xmpp_stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2); if (fin) { - xmpp_stanza_t* set = stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); + xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); if (set) { xmpp_stanza_t* last = xmpp_stanza_get_child_by_name(set, STANZA_NAME_LAST); char* lastid = xmpp_stanza_get_text(last); From d3303517f7bf3cea504f360518db6ea223036fac Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Thu, 28 Jan 2021 14:41:19 +0100 Subject: [PATCH 6/8] MAM: Request more pages via RSM Send another request with same jid and last id we got. --- src/xmpp/iq.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index e7648251..cc58db58 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -108,6 +108,12 @@ typedef struct command_config_data_t char* command; } CommandConfigData; +typedef struct mam_rsm_userdata +{ + char* barejid; + char* datestr; +} MamRsmUserdata; + static int _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata); static void _error_handler(xmpp_stanza_t* const stanza); @@ -2557,7 +2563,11 @@ iq_mam_request(ProfChatWin* win) gchar* datestr = g_date_time_format(timestamp, "%FT%TZ"); xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr, NULL); - iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, g_strdup(datestr)); + MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata)); + data->datestr = strdup(datestr); + data->barejid = strdup(win->barejid); + + iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data); g_free(datestr); g_date_time_unref(timestamp); @@ -2585,15 +2595,21 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) if (fin) { xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); if (set) { + char *lastid = NULL; xmpp_stanza_t* last = xmpp_stanza_get_child_by_name(set, STANZA_NAME_LAST); - char* lastid = xmpp_stanza_get_text(last); - lastid = lastid; + if (last) { + lastid = xmpp_stanza_get_text(last); + } // 4.3.2. send same stanza with set,max stanza xmpp_ctx_t* const ctx = connection_get_ctx(); - gchar *datestr = (gchar*)userdata; - //TODO give barejid or get from stanza - xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, NULL, datestr, lastid); + + MamRsmUserdata* data = (MamRsmUserdata*)userdata; + xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->datestr, lastid); + free(data->barejid); + free(data->datestr); + free(data); + free(lastid); iq_send_stanza(iq); xmpp_stanza_release(iq); From 840238b12671ae77ecfc8911879595816829486b Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Thu, 28 Jan 2021 14:42:13 +0100 Subject: [PATCH 7/8] Get MAM from last 7 days Probably should make this configurable later. --- src/xmpp/iq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index cc58db58..ed1af567 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2558,7 +2558,7 @@ iq_mam_request(ProfChatWin* win) xmpp_ctx_t* const ctx = connection_get_ctx(); GDateTime* now = g_date_time_new_now_utc(); - GDateTime* timestamp = g_date_time_add_days(now, -1); + GDateTime* timestamp = g_date_time_add_days(now, -7); g_date_time_unref(now); gchar* datestr = g_date_time_format(timestamp, "%FT%TZ"); xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, datestr, NULL); From c2ec3e7033b925343d973f4a40c0bab653791b7d Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Thu, 28 Jan 2021 14:43:44 +0100 Subject: [PATCH 8/8] Enable error logging on MAM RSM --- src/xmpp/iq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index ed1af567..5012d1a5 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -2583,13 +2583,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) { const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, "error") == 0) { - //TODO - /* char* error_message = stanza_get_error_message(stanza); cons_show_error("Server error: %s", error_message); - log_debug("Error: %s", error_message); + log_debug("MAM Error: %s", error_message); free(error_message); - */ } else if (g_strcmp0(type, "result") == 0) { xmpp_stanza_t* fin = xmpp_stanza_get_child_by_name_and_ns(stanza, STANZA_NAME_FIN, STANZA_NS_MAM2); if (fin) {