Original bug report: https://bugzilla.gnome.org/show_bug.cgi?id=659872
(I strongly suggest you to start reading Rob's bug reports on this issue).
- Connect your laptop to your docking station and make sure you have a wired (through the dock) and a wifi connection connected.
- Remove it from the docking station; the wired connectivity is lost and the wifi one becomes the default
- Empathy doesn't notice the connectivity change; each CM has to times out before reconnecting
Expected results: all the accounts are reconnected.
The main issue here is that we are relying exclusively on NM_STATE
changes to detect connectivity changes. This used to work fine when NM was
keeping only one connection at a time as a drop of this connection resulted in
a state change. But that's not the case since NM can now be connected to
different connections at the same time (typically a wired and a wifi
We should track and watch the default active connection and react propertly when it's changed.
A first implementation of this would be to assume that all CM connections are using the default IPv4 NM connection.
Later we could add API on Connection to let CMs tell us which interface they are actually using it and so improve the IPv6 and non-default route (cf Rob's bug) case.
*** Bug 48219 has been marked as a duplicate of this bug. ***
I've been thinking about this, and I think the right way to do this is within the CM. The CM knows which interface it's using to connect to the network, whereas MC would have to guess or ask.
GNetworkMonitor currently only monitors which routes are available (using netlink's RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE messages—see man 7 rtnetlink). This isn't enough to determine that your wired network, and hence your XMPP connection, is dead when your wireless is still up.
You can determine the source (local) IP address used by a socket with g_socket_get_local_address(), and you can monitor which IP addresses the system currently has with netlink's RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR messages. So, combining the two, the CM could forcibly close its socket after the socket's source IP is lost.
I believe this should cope with the case where two interfaces have the same IP address (Rob has, since his Empathy bug report, hacked the office DHCP server to assign him the same IP address on wired and wireless, which I /think/ makes his connections not break when he docks and undocks). I'm not sure how VPNs look.
Rather than forcibly closing the socket immediately, it could send a ping with a relatively short timeout. This would avoid killing connections unnecessarily if you unplug your wire for just a moment, and might make bugs in this code less disastrous. However, it would mean that the following scenario would still not work:
• Undock your laptop;
• Send an IM to say “I'll be there in 5 minutes”;
• And then the ping times out, your connection dies, and your message has been lost.
On XMPP, XEP-0198 is one answer to that—and a big advantage of having the CM do this kind of connectivity monitoring is that it would be possible for Gabble/Wocky to resume the stream and resend stanzas as necessary, without having to signal to MC and the user that the connection bounced.
(A half-way house would be to have the CM send a ping in response to GNetworkMonitor::network-changed, and blow up if it doesn't get a reply.)
This is /way/ simpler than having MC watch which interfaces are active, guess which one the CM is using (or have API for the CM to tell MC), etc etc.
I'm inclined to agree with Will: I think CMs should take responsibility for detecting when they've lost their network connections, because only the CM knows how much connectivity it actually needs, and more importantly, which local IP address it's actually using. Having MC try to guess is error-prone, and having the CM tell MC what's going on would need a significant amount of D-Bus API.
I'd be tempted to add something like this:
property Protocol.ConnectivityFlags: immutable readable Connectivity_Flags
# This CM does not need an Internet connection.
# (telepathy-ring, telepathy-salut)
# Connections for CM will automatically disconnect itself if
# required. MC shouldn't second-guess it.
and that'd give us 95% of the Conditions interface (Bug #24896) straight away. The rest is speculative generality about "what if I have a SIP account that should only be connected when I'm at the office, or when I'm on a particular VPN?" which, to be honest, could be implemented by manipulating the Enabled flag.
Agreed, closing this bug.
Reopening and assigning to 'general' since the suggested implementation involves CMs directly. If/when someone works on this, I suggest using this as a metabug for CM-specific bugs against Gabble, Salut, Rakia and Idle - Haze probably has to be WONTFIX since we don't have sufficiently fine control over its networking.
> You can determine the source (local) IP address used by a socket with
> g_socket_get_local_address(), and you can monitor which IP addresses the
> system currently has with netlink's RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR
> messages. So, combining the two, the CM could forcibly close its socket after
> the socket's source IP is lost.
> Rather than forcibly closing the socket immediately, it could send a ping
> with a relatively short timeout.
This Netlink monitoring could maybe go in telepathy-glib, but would be better in GIO.
> On XMPP, XEP-0198 is one answer
That's Bug #46700.
On Bug #41150, wjt wrote:
> Hmm, interesting. Actually, this could be a way to solve bug 41148:
> have MC just tell every CM to send a ping immediately when it sees any
> interface go down (if another interface is still up). This avoids us
> having to figure out which interface a connection is using to be able
> to deal properly with the "connect over wired, turn on wifi,
> unplug cable, connection doesn't realise it's dead" case.
> We'd have to fix bug 31815 in Wocky first, to make the pings actually
> time out and kill the connection if no answer is received.
I think we can even do this in CMs themselves without adding new D-Bus API, by having the CM watch the GNetworkMonitor and send a ping on any connectivity change (even if we still have connectivity).
*** Bug 41150 has been marked as a duplicate of this bug. ***