about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/command.c2
-rw-r--r--src/jabber.c62
-rw-r--r--src/jabber.h3
-rw-r--r--src/profanity.c31
-rw-r--r--src/profanity.h1
6 files changed, 75 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore
index cbf66597..9164595e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,4 @@ stamp-h1
 *~
 *dirstamp
 valgrind.out
+core
diff --git a/src/command.c b/src/command.c
index a34f6faa..eae52ae9 100644
--- a/src/command.c
+++ b/src/command.c
@@ -494,6 +494,8 @@ _cmd_connect(const char * const inp, struct cmd_help_t help)
 static gboolean
 _cmd_quit(const char * const inp, struct cmd_help_t help)
 {
+    log_info("Profanity is shutting down.");
+    profanity_shutdown_init();
     return FALSE;
 }
 
diff --git a/src/jabber.c b/src/jabber.c
index 3af7f203..c8ef4a55 100644
--- a/src/jabber.c
+++ b/src/jabber.c
@@ -31,6 +31,7 @@
 #include "jabber.h"
 #include "log.h"
 #include "preferences.h"
+#include "profanity.h"
 #include "ui.h"
 
 #define PING_INTERVAL 120000 // 2 minutes
@@ -157,16 +158,24 @@ jabber_get_jid(void)
     return xmpp_conn_get_jid(jabber_conn.conn);
 }
 
-void
+gboolean
 jabber_disconnect(void)
 {
+    // if connected, send end stream and wait for response
     if (jabber_conn.conn_status == JABBER_CONNECTED) {
         log_info("Closing connection");
-        xmpp_conn_release(jabber_conn.conn);
-        xmpp_ctx_free(jabber_conn.ctx);
-        xmpp_shutdown();
-        jabber_conn.conn_status = JABBER_DISCONNECTED;
-        jabber_conn.presence = PRESENCE_OFFLINE;
+        xmpp_disconnect(jabber_conn.conn);
+        jabber_conn.conn_status = JABBER_DISCONNECTING;
+        return TRUE;
+
+    // if disconnected dont wait just shutdown
+    } else if (jabber_conn.conn_status == JABBER_DISCONNECTED) {
+        log_info("No connection open");
+        return FALSE;
+
+    // any other states, just shutdown
+    } else {
+        return FALSE;
     }
 }
 
@@ -174,7 +183,8 @@ void
 jabber_process_events(void)
 {
     if (jabber_conn.conn_status == JABBER_CONNECTED 
-            || jabber_conn.conn_status == JABBER_CONNECTING)
+            || jabber_conn.conn_status == JABBER_CONNECTING
+            || jabber_conn.conn_status == JABBER_DISCONNECTING)
         xmpp_run_once(jabber_conn.ctx, 10);
 }
 
@@ -366,21 +376,43 @@ _jabber_conn_handler(xmpp_conn_t * const conn,
 
         jabber_conn.conn_status = JABBER_CONNECTED;
         jabber_conn.presence = PRESENCE_ONLINE;
-    }
-    else {
-        if (jabber_conn.conn_status == JABBER_CONNECTED) {
+    } else {
+    
+        // received close stream response from server after disconnect
+        if (jabber_conn.conn_status == JABBER_DISCONNECTING) {
+            // free memory for connection object and context
+            xmpp_conn_release(jabber_conn.conn);
+            xmpp_ctx_free(jabber_conn.ctx);
+
+            // shutdown libstrophe
+            xmpp_shutdown();
+
+            jabber_conn.conn_status = JABBER_DISCONNECTED;
+            jabber_conn.presence = PRESENCE_OFFLINE;
+
+            profanity_shutdown();
+            
+        // lost connection for unkown reason
+        } else if (jabber_conn.conn_status == JABBER_CONNECTED) {
             cons_bad_show("Lost connection.");
             log_info("Lost connection");
             win_disconnected();
+            win_page_off();
+            log_info("disconnected");
+            xmpp_stop(ctx);
+            jabber_conn.conn_status = JABBER_DISCONNECTED;
+            jabber_conn.presence = PRESENCE_OFFLINE;
+
+        // login attempt failed
         } else {
             cons_bad_show("Login failed.");
             log_info("Login failed");
+            win_page_off();
+            log_info("disconnected");
+            xmpp_stop(ctx);
+            jabber_conn.conn_status = JABBER_DISCONNECTED;
+            jabber_conn.presence = PRESENCE_OFFLINE;
         }
-        win_page_off();
-        log_info("disconnected");
-        xmpp_stop(ctx);
-        jabber_conn.conn_status = JABBER_DISCONNECTED;
-        jabber_conn.presence = PRESENCE_OFFLINE;
     }
 }
 
diff --git a/src/jabber.h b/src/jabber.h
index b717fe2d..4a27c55a 100644
--- a/src/jabber.h
+++ b/src/jabber.h
@@ -27,6 +27,7 @@ typedef enum {
     JABBER_STARTED,
     JABBER_CONNECTING,
     JABBER_CONNECTED,
+    JABBER_DISCONNECTING,
     JABBER_DISCONNECTED
 } jabber_conn_status_t;
 
@@ -44,7 +45,7 @@ jabber_conn_status_t jabber_connection_status(void);
 jabber_presence_t jabber_presence_status(void);
 jabber_conn_status_t jabber_connect(const char * const user, 
     const char * const passwd);
-void jabber_disconnect(void);
+gboolean jabber_disconnect(void);
 void jabber_roster_request(void);
 void jabber_process_events(void);
 void jabber_send(const char * const msg, const char * const recipient);
diff --git a/src/profanity.c b/src/profanity.c
index 48f20e6c..ab5f2285 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -32,11 +32,11 @@
 #include "history.h"
 #include "log.h"
 #include "preferences.h"
+#include "profanity.h"
 #include "ui.h"
 
 static log_level_t _get_log_level(char *log_level);
 gboolean _process_input(char *inp);
-static void _profanity_shutdown(void);
 static void _create_config_directory();
 
 void
@@ -85,19 +85,32 @@ profanity_init(const int disable_tls, char *log_level)
     cmd_init();
     log_info("Initialising contact list");
     contact_list_init();
-    atexit(_profanity_shutdown);
+    atexit(profanity_shutdown_init);
 }
 
 void
-_profanity_shutdown(void)
+profanity_shutdown_init(void)
 {
     log_info("Profanity is shutting down.");
-    jabber_disconnect();
-    gui_close();
-    chat_log_close();
-    prefs_close();
-    log_info("Shutdown complete");
-    log_close();
+    gboolean wait_response = jabber_disconnect();
+
+    if (wait_response) {
+        while (TRUE) {
+            jabber_process_events();
+        }
+    }
+
+    profanity_shutdown();
+}
+
+void
+profanity_shutdown(void)
+{
+    gui_close();                                                          
+    chat_log_close();                                                    
+    prefs_close();                                                       
+    log_info("Shutdown complete");                                       
+    log_close();   
 }
 
 static log_level_t 
diff --git a/src/profanity.h b/src/profanity.h
index e0d01a23..b04c3a52 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -25,6 +25,7 @@
 
 void profanity_init(const int disable_tls, char *log_level);
 void profanity_run(void);
+void profanity_shutdown_init(void);
 void profanity_shutdown(void);
 
 #endif