From a704838152b9aec0bef2446f742b1eb548f71d1a Mon Sep 17 00:00:00 2001 From: MarcoPolo-PasTonMolo Date: Sat, 20 Aug 2022 22:48:02 +0300 Subject: Handle late delivery --- src/xmpp/iq.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 19 deletions(-) (limited to 'src/xmpp/iq.c') diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c index a1784b45..4c1ec90b 100644 --- a/src/xmpp/iq.c +++ b/src/xmpp/iq.c @@ -109,9 +109,17 @@ typedef struct mam_rsm_userdata char* barejid; char* start_datestr; char* end_datestr; + gboolean fetch_next; ProfChatWin* win; } MamRsmUserdata; +typedef struct late_delivery_userdata +{ + ProfChatWin* win; + GDateTime* enddate; + GDateTime* startdate; +} LateDeliveryUserdata; + 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); @@ -149,6 +157,7 @@ static int _command_exec_response_handler(xmpp_stanza_t* const stanza, void* con static int _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata); static int _register_change_password_result_id_handler(xmpp_stanza_t* const stanza, void* const userdata); +static void _iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate); static void _iq_free_room_data(ProfRoomInfoData* roominfo); static void _iq_free_affiliation_set(ProfPrivilegeSet* affiliation_set); static void _iq_free_affiliation_list(ProfAffiliationList* affiliation_list); @@ -164,6 +173,8 @@ static gboolean autoping_wait = FALSE; static GTimer* autoping_time = NULL; static GHashTable* id_handlers; static GHashTable* rooms_cache = NULL; +static GSList* late_delivery_windows = NULL; +static gboolean received_disco_items = FALSE; static int _iq_handler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const userdata) @@ -258,6 +269,8 @@ iq_handlers_init(void) id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_iq_id_handler_free); rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release); + late_delivery_windows = malloc(sizeof(GSList *)); + late_delivery_windows->data = NULL; } void @@ -2525,7 +2538,16 @@ _disco_items_result_handler(xmpp_stanza_t* const stanza) if (g_strcmp0(id, "discoitemsreq") == 0) { cons_show_disco_items(items, from); } else if (g_strcmp0(id, "discoitemsreq_onconnect") == 0) { + received_disco_items = TRUE; connection_set_disco_items(items); + + while (late_delivery_windows->data) { + LateDeliveryUserdata* del_data = late_delivery_windows->data; + _iq_mam_request(del_data->win, del_data->startdate, del_data->enddate); + + late_delivery_windows = g_slist_next(late_delivery_windows); + free(del_data); + } } g_slist_free_full(items, (GDestroyNotify)_item_destroy); @@ -2622,7 +2644,7 @@ iq_mam_request_older(ProfChatWin* win) } void -iq_mam_request(ProfChatWin* win) +_iq_mam_request(ProfChatWin* win, GDateTime* startdate, GDateTime* enddate) { if (connection_supports(XMPP_FEATURE_MAM2) == FALSE) { log_warning("Server doesn't advertise %s feature.", XMPP_FEATURE_MAM2); @@ -2630,43 +2652,72 @@ iq_mam_request(ProfChatWin* win) return; } - ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE); - // To get last page and have flipped paging set firstid to empty string char* firstid = ""; - char* startdate = NULL; - char* enddate = NULL; - - // If last message found - if (last_msg->timestamp) { - startdate = g_date_time_format(last_msg->timestamp, "%FT%T.%f%:z"); - } else { + char* startdate_str = NULL; + char* enddate_str = NULL; + gboolean fetch_next = FALSE; + + if (startdate) { + startdate_str = g_date_time_format(startdate, "%FT%T.%f%:z"); + fetch_next = TRUE; + g_date_time_unref(startdate); + } else if (!enddate) { GDateTime* now = g_date_time_new_now_utc(); - enddate = g_date_time_format(now, "%FT%T.%f%:z"); + enddate_str = g_date_time_format(now, "%FT%T.%f%:z"); g_date_time_unref(now); } + if (enddate) { + enddate_str = g_date_time_format(enddate, "%FT%T.%f%:z"); + g_date_time_unref(enddate); + } + xmpp_ctx_t* const ctx = connection_get_ctx(); - xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate, enddate, firstid, NULL); + xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, win->barejid, startdate_str, enddate_str, firstid, NULL); MamRsmUserdata* data = malloc(sizeof(MamRsmUserdata)); if (data) { - data->start_datestr = startdate; - data->end_datestr = enddate; + data->start_datestr = startdate_str; + data->end_datestr = enddate_str; data->barejid = strdup(win->barejid); + data->fetch_next = fetch_next; data->win = win; iq_id_handler_add(xmpp_stanza_get_id(iq), _mam_rsm_id_handler, NULL, data); } - message_free(last_msg); - iq_send_stanza(iq); xmpp_stanza_release(iq); return; } +void +iq_mam_request(ProfChatWin* win, GDateTime* enddate) +{ + ProfMessage* last_msg = log_database_get_limits_info(win->barejid, TRUE); + GDateTime* startdate = last_msg->timestamp ? g_date_time_add_seconds(last_msg->timestamp, 0) : NULL; // copy timestamp + message_free(last_msg); + + // Save request for later if disco items haven't been received yet + if (!received_disco_items) { + if (late_delivery_windows->data == NULL) { + LateDeliveryUserdata* cur_del_data = malloc(sizeof(LateDeliveryUserdata)); + cur_del_data->win = win; + cur_del_data->enddate = enddate; + cur_del_data->startdate = startdate; + late_delivery_windows->data = cur_del_data; + } + late_delivery_windows = g_slist_append(late_delivery_windows, NULL); + } + + + _iq_mam_request(win, startdate, enddate); + + return; +} + static int _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) { @@ -2684,11 +2735,39 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) ProfWin* window = (ProfWin*)data->win; buffer_remove_entry(window->layout->buffer, 0); - if (is_complete || data->end_datestr) { - chatwin_db_history(data->win, is_complete ? NULL : data->start_datestr, NULL, TRUE); + + char *start_str = NULL; + if (data->start_datestr) { + start_str = strdup(data->start_datestr); + // Convert to iso8601 + start_str[strlen(start_str) - 3] = '\0'; + } + char *end_str = NULL; + if (data->end_datestr) { + end_str = strdup(data->end_datestr); + // Convert to iso8601 + end_str[strlen(end_str) - 3] = '\0'; + } + + if (is_complete || !data->fetch_next) { + chatwin_db_history(data->win, is_complete ? NULL : start_str, end_str, TRUE); + // TODO free memory + if (start_str) { + free(start_str); + free(data->start_datestr); + } + + if (end_str) { + free(data->end_datestr); + } + + free(data->barejid); + free(data); return 0; } - chatwin_db_history(data->win, data->start_datestr, NULL, TRUE); + + chatwin_db_history(data->win, start_str, end_str, TRUE); + if (start_str) free(start_str); xmpp_stanza_t* set = xmpp_stanza_get_child_by_name_and_ns(fin, STANZA_TYPE_SET, STANZA_NS_RSM); if (set) { @@ -2701,6 +2780,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata) // 4.3.2. send same stanza with set,max stanza xmpp_ctx_t* const ctx = connection_get_ctx(); + if (end_str) { + free(data->end_datestr); + } + data->end_datestr = NULL; xmpp_stanza_t* iq = stanza_create_mam_iq(ctx, data->barejid, data->start_datestr, data->end_datestr, firstid, NULL); free(firstid); -- cgit 1.4.1-2-gfad0