From 1985fe1d7b94bd1eff80bb3da14bbc52e5585163 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Wed, 27 Nov 2019 18:46:29 +0100 Subject: [PATCH] Don't continue reading after stream was disconnected, make disconnecting async fixes #636 --- libdino/src/application.vala | 2 +- libdino/src/service/connection_manager.vala | 25 +++++++++++++-------- libdino/src/service/registration.vala | 6 ++--- libdino/src/service/stream_interactor.vala | 4 ++-- xmpp-vala/src/core/xmpp_stream.vala | 23 +++++++++++-------- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/libdino/src/application.vala b/libdino/src/application.vala index 23508bf4..9c53d88a 100644 --- a/libdino/src/application.vala +++ b/libdino/src/application.vala @@ -117,7 +117,7 @@ public interface Dino.Application : GLib.Application { protected void remove_connection(Account account) { if ((get_flags() & ApplicationFlags.IS_SERVICE) == ApplicationFlags.IS_SERVICE) release(); - stream_interactor.disconnect_account(account); + stream_interactor.disconnect_account.begin(account); } private void restore() { diff --git a/libdino/src/service/connection_manager.vala b/libdino/src/service/connection_manager.vala index 0a129717..000a4bfa 100644 --- a/libdino/src/service/connection_manager.vala +++ b/libdino/src/service/connection_manager.vala @@ -131,11 +131,11 @@ public class ConnectionManager : Object { connections[account].stream.get_module(Presence.Module.IDENTITY).send_presence(connections[account].stream, presence); } - public void disconnect_account(Account account) { + public async void disconnect_account(Account account) { if (connections.has_key(account)) { make_offline(account); try { - connections[account].stream.disconnect(); + yield connections[account].stream.disconnect(); } catch (Error e) { debug("Error disconnecting stream: %s", e.message); } @@ -217,6 +217,8 @@ public class ConnectionManager : Object { } private void check_reconnect(Account account) { + if (!connections.has_key(account)) return; + bool acked = false; DateTime? last_activity_was = connections[account].last_activity; @@ -228,6 +230,7 @@ public class ConnectionManager : Object { }); Timeout.add_seconds(10, () => { + if (!connections.has_key(account)) return false; if (connections[account].stream != stream) return false; if (acked) return false; if (connections[account].last_activity != last_activity_was) return false; @@ -235,11 +238,15 @@ public class ConnectionManager : Object { // Reconnect. Nothing gets through the stream. debug("[%s %p] Ping timeouted. Reconnecting", account.bare_jid.to_string(), stream); change_connection_state(account, ConnectionState.DISCONNECTED); - try { - connections[account].stream.disconnect(); - } catch (Error e) { - debug("Error disconnecting stream: %s", e.message); - } + + connections[account].stream.disconnect.begin((_, res) => { + try { + connections[account].stream.disconnect.end(res); + } catch (Error e) { + debug("Error disconnecting stream: %s", e.message); + } + }); + connect_(account); return false; }); @@ -267,7 +274,7 @@ public class ConnectionManager : Object { } } - private void on_prepare_for_sleep(bool suspend) { + private async void on_prepare_for_sleep(bool suspend) { foreach (Account account in connection_todo) { change_connection_state(account, ConnectionState.DISCONNECTED); } @@ -276,7 +283,7 @@ public class ConnectionManager : Object { foreach (Account account in connection_todo) { try { make_offline(account); - connections[account].stream.disconnect(); + yield connections[account].stream.disconnect(); } catch (Error e) { debug("Error disconnecting stream %p: %s", connections[account].stream, e.message); } diff --git a/libdino/src/service/registration.vala b/libdino/src/service/registration.vala index 20ea6063..19eebb05 100644 --- a/libdino/src/service/registration.vala +++ b/libdino/src/service/registration.vala @@ -37,7 +37,7 @@ public class Register : StreamInteractionModule, Object{ if (connected_account.equals(account)) { ret = error.source; } - stream_interactor.disconnect_account(account); + stream_interactor.disconnect_account.begin(account); Idle.add((owned)callback); }); @@ -91,7 +91,7 @@ public class Register : StreamInteractionModule, Object{ yield; try { - stream.disconnect(); + yield stream.disconnect(); } catch (Error e) {} return ret; } @@ -130,7 +130,7 @@ public class Register : StreamInteractionModule, Object{ form = yield stream.get_module(Xep.InBandRegistration.Module.IDENTITY).get_from_server(stream, jid); } try { - stream.disconnect(); + yield stream.disconnect(); } catch (Error e) {} return form; diff --git a/libdino/src/service/stream_interactor.vala b/libdino/src/service/stream_interactor.vala index d9074fb7..a1770bb8 100644 --- a/libdino/src/service/stream_interactor.vala +++ b/libdino/src/service/stream_interactor.vala @@ -29,8 +29,8 @@ public class StreamInteractor : Object { connection_manager.connect_account(account); } - public void disconnect_account(Account account) { - connection_manager.disconnect_account(account); + public async void disconnect_account(Account account) { + yield connection_manager.disconnect_account(account); account_removed(account); } diff --git a/xmpp-vala/src/core/xmpp_stream.vala b/xmpp-vala/src/core/xmpp_stream.vala index 44ecabb4..820d7ce8 100644 --- a/xmpp-vala/src/core/xmpp_stream.vala +++ b/xmpp-vala/src/core/xmpp_stream.vala @@ -27,6 +27,7 @@ public class XmppStream { public bool negotiation_complete { get; set; default=false; } private bool setup_needed = false; private bool non_negotiation_modules_attached = false; + private bool disconnected = false; public signal void received_node(XmppStream stream, StanzaNode node); public signal void received_root_node(XmppStream stream, StanzaNode node); @@ -75,15 +76,15 @@ public class XmppStream { yield loop(); } - public void disconnect() throws IOStreamError { - StanzaWriter? writer = this.writer; - StanzaReader? reader = this.reader; - IOStream? stream = this.stream; - if (writer == null || reader == null || stream == null) throw new IOStreamError.DISCONNECT("trying to disconnect, but no stream open"); + public async void disconnect() throws IOStreamError, XmlError, IOError { + disconnected = true; + if (writer == null || reader == null || stream == null) { + throw new IOStreamError.DISCONNECT("trying to disconnect, but no stream open"); + } log.str("OUT", ""); - ((!)writer).write.begin(""); - ((!)reader).cancel(); - ((!)stream).close_async.begin(); + yield writer.write(""); + reader.cancel(); + yield stream.close_async(); } public void reset_stream(IOStream stream) { @@ -217,6 +218,8 @@ public class XmppStream { Idle.add(loop.callback); yield; + if (disconnected) break; + received_node(this, node); if (node.ns_uri == NS_URI && node.name == "features") { @@ -224,7 +227,9 @@ public class XmppStream { received_features_node(this); } else if (node.ns_uri == NS_URI && node.name == "stream" && node.pseudo) { debug("[%p] Server closed stream", this); - disconnect(); + try { + yield disconnect(); + } catch (Error e) {} return; } else if (node.ns_uri == JABBER_URI) { if (node.name == "message") {