about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/profanity.c1
-rw-r--r--src/xmpp/connection.c63
-rw-r--r--src/xmpp/iq.c25
-rw-r--r--src/xmpp/xmpp.h3
-rw-r--r--tests/unittests/xmpp/stub_xmpp.c1
5 files changed, 81 insertions, 12 deletions
diff --git a/src/profanity.c b/src/profanity.c
index 6e973a72..51609582 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -124,6 +124,7 @@ prof_run(char *log_level, char *account_name)
 #endif
         notify_remind();
         jabber_process_events(10);
+        iq_autoping_check();
         ui_update();
     }
 }
diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c
index 42293c18..5390197f 100644
--- a/src/xmpp/connection.c
+++ b/src/xmpp/connection.c
@@ -104,7 +104,7 @@ static jabber_conn_status_t _jabber_connect(const char *const fulljid, const cha
     const char *const altdomain, int port, const char *const tls_policy);
 
 static void _jabber_reconnect(void);
-
+static void _jabber_lost_connection(void);
 static void _connection_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status, const int error,
     xmpp_stream_error_t *const stream_error, void *const userdata);
 
@@ -202,6 +202,35 @@ jabber_connect_with_details(const char *const jid, const char *const passwd, con
 }
 
 void
+jabber_ping_fail(void)
+{
+    if (jabber_conn.conn_status == JABBER_CONNECTED) {
+        log_info("Closing connection");
+        accounts_set_last_activity(jabber_get_account_name());
+        jabber_conn.conn_status = JABBER_DISCONNECTING;
+        xmpp_disconnect(jabber_conn.conn);
+
+        while (jabber_get_connection_status() == JABBER_DISCONNECTING) {
+            jabber_process_events(10);
+        }
+        if (jabber_conn.conn) {
+            xmpp_conn_release(jabber_conn.conn);
+            jabber_conn.conn = NULL;
+        }
+        if (jabber_conn.ctx) {
+            xmpp_ctx_free(jabber_conn.ctx);
+            jabber_conn.ctx = NULL;
+        }
+    }
+
+    FREE_SET_NULL(jabber_conn.presence_message);
+    FREE_SET_NULL(jabber_conn.domain);
+
+    jabber_conn.conn_status = JABBER_DISCONNECTED;
+    _jabber_lost_connection();
+}
+
+void
 jabber_disconnect(void)
 {
     // if connected, send end stream and wait for response
@@ -281,6 +310,12 @@ jabber_get_connection_status(void)
     return (jabber_conn.conn_status);
 }
 
+void
+jabber_set_connection_status(jabber_conn_status_t status)
+{
+    jabber_conn.conn_status = status;
+}
+
 xmpp_conn_t*
 connection_get_conn(void)
 {
@@ -543,6 +578,20 @@ _jabber_reconnect(void)
 }
 
 static void
+_jabber_lost_connection(void)
+{
+    sv_ev_lost_connection();
+    if (prefs_get_reconnect() != 0) {
+        assert(reconnect_timer == NULL);
+        reconnect_timer = g_timer_new();
+    } else {
+        _connection_free_saved_account();
+        _connection_free_saved_details();
+    }
+    _connection_free_session_data();
+}
+
+static void
 _connection_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status, const int error,
     xmpp_stream_error_t *const stream_error, void *const userdata)
 {
@@ -600,17 +649,7 @@ _connection_handler(xmpp_conn_t *const conn, const xmpp_conn_event_t status, con
         // lost connection for unknown reason
         if (jabber_conn.conn_status == JABBER_CONNECTED) {
             log_debug("Connection handler: Lost connection for unknown reason");
-            sv_ev_lost_connection();
-            if (prefs_get_reconnect() != 0) {
-                assert(reconnect_timer == NULL);
-                reconnect_timer = g_timer_new();
-                // free resources but leave saved_user untouched
-                _connection_free_session_data();
-            } else {
-                _connection_free_saved_account();
-                _connection_free_saved_details();
-                _connection_free_session_data();
-            }
+            _jabber_lost_connection();
 
         // login attempt failed
         } else if (jabber_conn.conn_status != JABBER_DISCONNECTING) {
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index dc1bbc4a..1fa5ffcc 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -99,6 +99,7 @@ static int _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t
 static int _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata);
 
 static gboolean autoping_wait = FALSE;
+static GTimer *autoping_time;
 
 void
 iq_add_handlers(void)
@@ -126,6 +127,28 @@ iq_add_handlers(void)
 }
 
 void
+iq_autoping_check(void)
+{
+    if (jabber_get_connection_status() != JABBER_CONNECTED) {
+        return;
+    }
+
+    if (autoping_wait == FALSE) {
+        return;
+    }
+
+    gdouble elapsed = g_timer_elapsed(autoping_time, NULL);
+    unsigned long seconds_elapsed = elapsed * 1.0;
+    log_debug("Autoping check: waiting, %u", seconds_elapsed);
+    if (seconds_elapsed > 5) {
+        // disconnect
+        jabber_ping_fail();
+        autoping_wait = FALSE;
+        g_timer_destroy(autoping_time);
+    }
+}
+
+void
 iq_set_autoping(const int seconds)
 {
     if (jabber_get_connection_status() != JABBER_CONNECTED) {
@@ -529,6 +552,7 @@ static int
 _auto_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata)
 {
     autoping_wait = FALSE;
+    g_timer_destroy(autoping_time);
 
     char *id = xmpp_stanza_get_id(stanza);
     if (id == NULL) {
@@ -870,6 +894,7 @@ _autoping_timed_handler(xmpp_conn_t *const conn, void *const userdata)
     xmpp_send(conn, iq);
     xmpp_stanza_release(iq);
     autoping_wait = TRUE;
+    autoping_time = g_timer_new();
 
     return 1;
 }
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index f52603eb..883c4f13 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -144,10 +144,12 @@ jabber_conn_status_t jabber_connect_with_details(const char *const jid, const ch
 jabber_conn_status_t jabber_connect_with_account(const ProfAccount *const account);
 void jabber_disconnect(void);
 void jabber_shutdown(void);
+void jabber_ping_fail(void);
 void jabber_process_events(int millis);
 const char* jabber_get_fulljid(void);
 const char* jabber_get_domain(void);
 jabber_conn_status_t jabber_get_connection_status(void);
+void jabber_set_connection_status(jabber_conn_status_t status);
 char* jabber_get_presence_message(void);
 char* jabber_get_account_name(void);
 GList* jabber_get_available_resources(void);
@@ -212,6 +214,7 @@ void iq_room_affiliation_set(const char *const room, const char *const jid, char
 void iq_room_kick_occupant(const char *const room, const char *const nick, const char *const reason);
 void iq_room_role_set(const char *const room, const char *const nick, char *role, const char *const reason);
 void iq_room_role_list(const char * const room, char *role);
+void iq_autoping_check(void);
 
 // caps functions
 Capabilities* caps_lookup(const char *const jid);
diff --git a/tests/unittests/xmpp/stub_xmpp.c b/tests/unittests/xmpp/stub_xmpp.c
index 6abec1bf..dc630198 100644
--- a/tests/unittests/xmpp/stub_xmpp.c
+++ b/tests/unittests/xmpp/stub_xmpp.c
@@ -173,6 +173,7 @@ void iq_room_role_set(const char * const room, const char * const nick, char *ro
     const char * const reason) {}
 void iq_room_role_list(const char * const room, char *role) {}
 void iq_last_activity_request(gchar *jid) {}
+void iq_autoping_check(void) {}
 
 // caps functions
 Capabilities* caps_lookup(const char * const jid)