about summary refs log tree commit diff stats
path: root/src/xmpp/iq.c
diff options
context:
space:
mode:
authorMarcoPolo-PasTonMolo <marcopolopastonmolo@protonmail.com>2022-08-20 22:48:02 +0300
committerMarcoPolo-PasTonMolo <marcopolopastonmolo@protonmail.com>2022-08-20 22:48:02 +0300
commita704838152b9aec0bef2446f742b1eb548f71d1a (patch)
treeaed0eba30c8f27cb4f310b66752cd2fee30ba776 /src/xmpp/iq.c
parent4b9ff6d4dcf2e1c16f12f9039d57530245ce1c4d (diff)
downloadprofani-tty-a704838152b9aec0bef2446f742b1eb548f71d1a.tar.gz
Handle late delivery
Diffstat (limited to 'src/xmpp/iq.c')
-rw-r--r--src/xmpp/iq.c121
1 files changed, 102 insertions, 19 deletions
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);