about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/event/server_events.c1
-rw-r--r--src/xmpp/roster_list.c43
-rw-r--r--src/xmpp/roster_list.h1
-rw-r--r--tests/unittests/test_server_events.c5
4 files changed, 50 insertions, 0 deletions
diff --git a/src/event/server_events.c b/src/event/server_events.c
index 4366b2ab..4644cc8c 100644
--- a/src/event/server_events.c
+++ b/src/event/server_events.c
@@ -115,6 +115,7 @@ sv_ev_roster_received(void)
         ui_show_roster();
     }
 
+    roster_process_pending_presence();
     char *account_name = session_get_account_name();
 
 #ifdef HAVE_LIBGPGME
diff --git a/src/xmpp/roster_list.c b/src/xmpp/roster_list.c
index 5ebdc08f..81a51581 100644
--- a/src/xmpp/roster_list.c
+++ b/src/xmpp/roster_list.c
@@ -67,7 +67,15 @@ typedef struct prof_roster_t {
     GHashTable *group_count;
 } ProfRoster;
 
+typedef struct pending_presence {
+    char *barejid;
+    Resource *resource;
+    GDateTime *last_activity;
+} ProfPendingPresence;
+
 static ProfRoster *roster = NULL;
+static gboolean roster_received = FALSE;
+static GSList *roster_pending_presence = NULL;
 
 static gboolean _key_equals(void *key1, void *key2);
 static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2);
@@ -87,6 +95,9 @@ roster_create(void)
     roster->name_to_barejid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
     roster->groups_ac = autocomplete_new();
     roster->group_count = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+    roster_received = FALSE;
+    roster_pending_presence = NULL;
 }
 
 void
@@ -114,6 +125,18 @@ roster_update_presence(const char *const barejid, Resource *resource, GDateTime
     assert(barejid != NULL);
     assert(resource != NULL);
 
+    if (!roster_received) {
+        ProfPendingPresence *presence = malloc(sizeof(ProfPendingPresence));
+        presence->barejid = strdup(barejid);
+        presence->resource = resource;
+        presence->last_activity = last_activity;
+        if (last_activity) {
+            g_date_time_ref(last_activity);
+        }
+        roster_pending_presence = g_slist_append(roster_pending_presence, presence);
+        return FALSE;
+    }
+
     PContact contact = roster_get_contact(barejid);
     if (contact == NULL) {
         return FALSE;
@@ -664,3 +687,23 @@ roster_compare_presence(PContact a, PContact b)
         return roster_compare_name(a, b);
     }
 }
+
+void
+roster_process_pending_presence(void)
+{
+    roster_received = TRUE;
+
+    GSList *iter;
+    for (iter = roster_pending_presence; iter != NULL; iter = iter->next) {
+        ProfPendingPresence *presence = iter->data;
+        roster_update_presence(presence->barejid, presence->resource, presence->last_activity);
+        free(presence->barejid);
+        /* seems like resource isn't free on the calling side */
+        if (presence->last_activity) {
+            g_date_time_unref(presence->last_activity);
+        }
+    }
+
+    g_slist_free(roster_pending_presence);
+    roster_pending_presence = NULL;
+}
diff --git a/src/xmpp/roster_list.h b/src/xmpp/roster_list.h
index 5120043c..57a932be 100644
--- a/src/xmpp/roster_list.h
+++ b/src/xmpp/roster_list.h
@@ -72,5 +72,6 @@ GSList* roster_get_contacts_by_presence(const char *const presence);
 char* roster_get_msg_display_name(const char *const barejid, const char *const resource);
 gint roster_compare_name(PContact a, PContact b);
 gint roster_compare_presence(PContact a, PContact b);
+void roster_process_pending_presence(void);
 
 #endif
diff --git a/tests/unittests/test_server_events.c b/tests/unittests/test_server_events.c
index a00eedfd..282c1ffe 100644
--- a/tests/unittests/test_server_events.c
+++ b/tests/unittests/test_server_events.c
@@ -21,6 +21,7 @@ void console_shows_online_presence_when_set_online(void **state)
     prefs_set_string(PREF_STATUSES_CONSOLE, "online");
     plugins_init();
     roster_create();
+    roster_process_pending_presence();
     char *barejid = "test1@server";
     roster_add(barejid, "bob", NULL, "both", FALSE);
     Resource *resource = resource_new("resource", RESOURCE_ONLINE, NULL, 10);
@@ -40,6 +41,7 @@ void console_shows_online_presence_when_set_all(void **state)
     prefs_set_string(PREF_STATUSES_CONSOLE, "all");
     plugins_init();
     roster_create();
+    roster_process_pending_presence();
     char *barejid = "test1@server";
     roster_add(barejid, "bob", NULL, "both", FALSE);
     Resource *resource = resource_new("resource", RESOURCE_ONLINE, NULL, 10);
@@ -59,6 +61,7 @@ void console_shows_dnd_presence_when_set_all(void **state)
     prefs_set_string(PREF_STATUSES_CONSOLE, "all");
     plugins_init();
     roster_create();
+    roster_process_pending_presence();
     char *barejid = "test1@server";
     roster_add(barejid, "bob", NULL, "both", FALSE);
     Resource *resource = resource_new("resource", RESOURCE_ONLINE, NULL, 10);
@@ -77,6 +80,7 @@ void handle_offline_removes_chat_session(void **state)
 {
     plugins_init();
     roster_create();
+    roster_process_pending_presence();
     chat_sessions_init();
     char *barejid = "friend@server.chat.com";
     char *resource = "home";
@@ -100,6 +104,7 @@ void handle_offline_removes_chat_session(void **state)
 void lost_connection_clears_chat_sessions(void **state)
 {
     roster_create();
+    roster_process_pending_presence();
     chat_sessions_init();
     chat_session_recipient_active("bob@server.org", "laptop", FALSE);
     chat_session_recipient_active("steve@server.org", "mobile", FALSE);