diff options
-rw-r--r-- | libdino/src/service/connection_manager.vala | 36 | ||||
-rw-r--r-- | main/data/contact_details_dialog.ui | 1 | ||||
-rw-r--r-- | main/data/manage_accounts/dialog.ui | 3 | ||||
-rw-r--r-- | main/src/ui/manage_accounts/dialog.vala | 13 | ||||
-rw-r--r-- | xmpp-vala/src/core/stanza_reader.vala | 8 | ||||
-rw-r--r-- | xmpp-vala/src/core/stanza_writer.vala | 2 | ||||
-rw-r--r-- | xmpp-vala/src/core/xmpp_stream.vala | 43 | ||||
-rw-r--r-- | xmpp-vala/src/module/tls.vala | 4 |
8 files changed, 66 insertions, 44 deletions
diff --git a/libdino/src/service/connection_manager.vala b/libdino/src/service/connection_manager.vala index 5fcd66a2..bd22191f 100644 --- a/libdino/src/service/connection_manager.vala +++ b/libdino/src/service/connection_manager.vala @@ -32,12 +32,20 @@ public class ConnectionManager { public enum Source { CONNECTION, SASL, + TLS, STREAM_ERROR } + public enum Reconnect { + NOW, + LATER, + NEVER + } + public Source source; public string? identifier; - public StreamError.Flag? flag; + public Reconnect reconnect_recomendation { get; set; default=Reconnect.NOW; } + public bool resource_rejected = false; public ConnectionError(Source source, string? identifier) { this.source = source; @@ -79,7 +87,8 @@ public class ConnectionManager { } Timeout.add_seconds(60, () => { foreach (Account account in connection_todo) { - if (connections[account].last_activity.compare(new DateTime.now_utc().add_minutes(-1)) < 0) { + if (connections[account].last_activity != null && + connections[account].last_activity.compare(new DateTime.now_utc().add_minutes(-1)) < 0) { check_reconnect(account); } } @@ -164,7 +173,7 @@ public class ConnectionManager { change_connection_state(account, ConnectionState.CONNECTED); }); stream.get_module(PlainSasl.Module.IDENTITY).received_auth_failure.connect((stream, node) => { - set_connection_error(account, ConnectionError.Source.SASL, null); + set_connection_error(account, new ConnectionError(ConnectionError.Source.SASL, null)); change_connection_state(account, ConnectionState.DISCONNECTED); }); stream.received_node.connect(() => { @@ -186,9 +195,13 @@ public class ConnectionManager { connections.unset(account); return; } + if (e is Core.IOStreamError.TLS) { + set_connection_error(account, new ConnectionError(ConnectionError.Source.TLS, e.message) { reconnect_recomendation=ConnectionError.Reconnect.NEVER}); + return; + } StreamError.Flag? flag = stream.get_flag(StreamError.Flag.IDENTITY); if (flag != null) { - set_connection_error(account, ConnectionError.Source.STREAM_ERROR, flag.error_type); + set_connection_error(account, new ConnectionError(ConnectionError.Source.STREAM_ERROR, flag.error_type) { resource_rejected=flag.resource_rejected }); } interpret_connection_error(account); } @@ -199,17 +212,17 @@ public class ConnectionManager { int wait_sec = 5; if (error == null) { wait_sec = 3; - } else if (error.source == ConnectionError.Source.STREAM_ERROR && error.flag != null) { - if (error.flag.resource_rejected) { + } else if (error.source == ConnectionError.Source.STREAM_ERROR) { + if (error.resource_rejected) { connect_(account, account.resourcepart + "-" + random_uuid()); return; } - switch (error.flag.reconnection_recomendation) { - case StreamError.Flag.Reconnect.NOW: + switch (error.reconnect_recomendation) { + case ConnectionError.Reconnect.NOW: wait_sec = 5; break; - case StreamError.Flag.Reconnect.LATER: + case ConnectionError.Reconnect.LATER: wait_sec = 60; break; - case StreamError.Flag.Reconnect.NEVER: + case ConnectionError.Reconnect.NEVER: return; } } else if (error.source == ConnectionError.Source.SASL) { @@ -291,8 +304,7 @@ public class ConnectionManager { } } - private void set_connection_error(Account account, ConnectionError.Source source, string? id) { - ConnectionError error = new ConnectionError(source, id); + private void set_connection_error(Account account, ConnectionError error) { connection_errors[account] = error; connection_error(account, error); } diff --git a/main/data/contact_details_dialog.ui b/main/data/contact_details_dialog.ui index 8fa62398..8ce7306d 100644 --- a/main/data/contact_details_dialog.ui +++ b/main/data/contact_details_dialog.ui @@ -77,6 +77,7 @@ <child> <object class="GtkLabel" id="jid_label"> <property name="xalign">0</property> + <property name="yalign">0</property> <property name="selectable">True</property> <property name="expand">True</property> <property name="visible">True</property> diff --git a/main/data/manage_accounts/dialog.ui b/main/data/manage_accounts/dialog.ui index 9235f613..2dc2762b 100644 --- a/main/data/manage_accounts/dialog.ui +++ b/main/data/manage_accounts/dialog.ui @@ -88,6 +88,7 @@ <child> <object class="GtkBox"> <property name="visible">True</property> + <property name="halign">end</property> <child> <object class="GtkBox"> <property name="visible">True</property> @@ -121,6 +122,7 @@ <child> <object class="GtkLabel" id="jid_label"> <property name="xalign">0</property> + <property name="yalign">1</property> <property name="visible">True</property> <attributes> <attribute name="weight" value="PANGO_WEIGHT_BOLD"/> @@ -136,6 +138,7 @@ <child> <object class="GtkLabel" id="state_label"> <property name="xalign">0</property> + <property name="yalign">0</property> <property name="visible">True</property> <style> <class name="dim-label"/> diff --git a/main/src/ui/manage_accounts/dialog.vala b/main/src/ui/manage_accounts/dialog.vala index dd2383a2..b157a936 100644 --- a/main/src/ui/manage_accounts/dialog.vala +++ b/main/src/ui/manage_accounts/dialog.vala @@ -171,7 +171,7 @@ public class Dialog : Gtk.Dialog { } } - private bool on_active_switch_state_changed(bool state) { + private bool change_account_state(bool state) { selected_account.enabled = state; if (state) { if (selected_account.enabled) account_disabled(selected_account); @@ -189,7 +189,7 @@ public class Dialog : Gtk.Dialog { } private void populate_grid_data(Account account) { - active_switch.state_set.disconnect(on_active_switch_state_changed); + active_switch.state_set.disconnect(change_account_state); Util.image_set_from_scaled_pixbuf(image, (new AvatarGenerator(50, 50, image.scale_factor)).draw_account(stream_interactor, account)); active_switch.set_active(account.enabled); @@ -201,7 +201,7 @@ public class Dialog : Gtk.Dialog { update_status_label(account); - active_switch.state_set.connect(on_active_switch_state_changed); + active_switch.state_set.connect(change_account_state); foreach(Plugins.AccountSettingsWidget widget in plugin_widgets) { widget.set_account(account); @@ -216,8 +216,11 @@ public class Dialog : Gtk.Dialog { state_label.get_style_context().add_class("is_error"); if (error.source == ConnectionManager.ConnectionError.Source.SASL || - (error.flag != null && error.flag.reconnection_recomendation == Xmpp.StreamError.Flag.Reconnect.NEVER)) { + error.source == ConnectionManager.ConnectionError.Source.TLS || + error.reconnect_recomendation == ConnectionManager.ConnectionError.Reconnect.NEVER) { + active_switch.state_set.disconnect(change_account_state); active_switch.active = false; + active_switch.state_set.connect(change_account_state); } } else { @@ -238,6 +241,8 @@ public class Dialog : Gtk.Dialog { switch (error.source) { case ConnectionManager.ConnectionError.Source.SASL: return _("Wrong password"); + case ConnectionManager.ConnectionError.Source.TLS: + return _("Invalid TLS certificate"); } if (error.identifier != null) { return _("Error") + ": " + error.identifier; diff --git a/xmpp-vala/src/core/stanza_reader.vala b/xmpp-vala/src/core/stanza_reader.vala index 4b4d98ab..6a7520ba 100644 --- a/xmpp-vala/src/core/stanza_reader.vala +++ b/xmpp-vala/src/core/stanza_reader.vala @@ -7,12 +7,12 @@ public const string XML_URI = "http://www.w3.org/XML/1998/namespace"; public const string JABBER_URI = "jabber:client"; public errordomain XmlError { - XML_ERROR, NS_DICT_ERROR, UNSUPPORTED, EOF, BAD_XML, - IO_ERROR + IO, + TLS } public class StanzaReader { @@ -52,8 +52,10 @@ public class StanzaReader { buffer_fill = (int) yield ((!)input).read_async(buffer, GLib.Priority.DEFAULT, cancellable); if (buffer_fill == 0) throw new XmlError.EOF("End of input stream reached."); buffer_pos = 0; + } catch (TlsError e) { + throw new XmlError.TLS("TlsError: %s".printf(e.message)); } catch (GLib.IOError e) { - throw new XmlError.IO_ERROR("IOError in GLib: %s".printf(e.message)); + throw new XmlError.IO("GLib.IOError: %s".printf(e.message)); } } diff --git a/xmpp-vala/src/core/stanza_writer.vala b/xmpp-vala/src/core/stanza_writer.vala index 270d898d..62c870de 100644 --- a/xmpp-vala/src/core/stanza_writer.vala +++ b/xmpp-vala/src/core/stanza_writer.vala @@ -30,7 +30,7 @@ public class StanzaWriter { sfw.sfun(); } } catch (GLib.Error e) { - throw new XmlError.IO_ERROR(@"IOError in GLib: $(e.message)"); + throw new XmlError.IO(@"IOError in GLib: $(e.message)"); } finally { running = false; } diff --git a/xmpp-vala/src/core/xmpp_stream.vala b/xmpp-vala/src/core/xmpp_stream.vala index ea186a72..6d4b9c64 100644 --- a/xmpp-vala/src/core/xmpp_stream.vala +++ b/xmpp-vala/src/core/xmpp_stream.vala @@ -6,8 +6,8 @@ public errordomain IOStreamError { READ, WRITE, CONNECT, - DISCONNECT - + DISCONNECT, + TLS } public class XmppStream { @@ -58,10 +58,13 @@ public class XmppStream { IOStream? stream = null; if (best_provider != null) { stream = yield best_provider.connect(this); - } else { + } + if (stream != null) { stream = yield (new SocketClient()).connect_async(new NetworkService("xmpp-client", "tcp", this.remote_name)); } - if (stream == null) throw new IOStreamError.CONNECT("client.connect() returned null"); + if (stream == null) { + throw new IOStreamError.CONNECT("client.connect() returned null"); + } reset_stream((!)stream); } catch (Error e) { stderr.printf("CONNECTION LOST?\n"); @@ -154,7 +157,10 @@ public class XmppStream { } public void detach_modules() { - foreach (XmppStreamModule module in modules) module.detach(this); + foreach (XmppStreamModule module in modules) { + if (!(module is XmppStreamNegotiationModule) && !negotiation_complete) continue; + module.detach(this); + } } public T? get_module<T>(ModuleIdentity<T>? identity) { @@ -238,23 +244,18 @@ public class XmppStream { } private bool negotiation_modules_done() throws IOStreamError { - if (!setup_needed) { - bool mandatory_outstanding = false; - foreach (XmppStreamModule module in modules) { - if (module is XmppStreamNegotiationModule) { - XmppStreamNegotiationModule negotiation_module = (XmppStreamNegotiationModule) module; - if (negotiation_module.mandatory_outstanding(this)) mandatory_outstanding = true; - } - } - if (!is_negotiation_active()) { - if (mandatory_outstanding) { - throw new IOStreamError.CONNECT("mandatory-to-negotiate feature not negotiated"); - } else { - return true; + if (setup_needed) return false; + if (is_negotiation_active()) return false; + + foreach (XmppStreamModule module in modules) { + if (module is XmppStreamNegotiationModule) { + XmppStreamNegotiationModule negotiation_module = (XmppStreamNegotiationModule) module; + if (negotiation_module.mandatory_outstanding(this)) { + throw new IOStreamError.CONNECT("mandatory-to-negotiate feature not negotiated: " + negotiation_module.get_id()); } } } - return false; + return true; } private void attach_non_negotation_modules() { @@ -281,7 +282,9 @@ public class XmppStream { StanzaNode node = yield ((!)reader).read_root_node(); log.node("IN ROOT", node); return node; - } catch (XmlError e) { + } catch (XmlError.TLS e) { + throw new IOStreamError.TLS(e.message); + } catch (Error e) { throw new IOStreamError.READ(e.message); } } diff --git a/xmpp-vala/src/module/tls.vala b/xmpp-vala/src/module/tls.vala index dcd7ab40..5defc72c 100644 --- a/xmpp-vala/src/module/tls.vala +++ b/xmpp-vala/src/module/tls.vala @@ -27,10 +27,6 @@ namespace Xmpp.Tls { var io_stream = stream.get_stream(); if (io_stream == null) return; var conn = TlsClientConnection.new(io_stream, identity); - // TODO: Add certificate error handling, that is, allow the - // program to handle certificate errors. The certificate - // *is checked* by TlsClientConnection, and connection is - // not allowed to continue in case that there is an error. stream.reset_stream(conn); var flag = stream.get_flag(Flag.IDENTITY); |