changeset 3125:c3ce8c997fdf

plugin android: reconnect profiles with autoconnect if network is activated: if network is activated, we check that all profiles with autoconnect are indeed connected, and reconnect them if necesssary.
author Goffi <goffi@goffi.org>
date Sun, 26 Jan 2020 18:08:09 +0100
parents b86060901278
children 2b0f739f8a46
files sat/core/sat_main.py sat/core/xmpp.py sat/plugins/plugin_misc_android.py
diffstat 3 files changed, 36 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/sat/core/sat_main.py	Sat Jan 25 21:08:41 2020 +0100
+++ b/sat/core/sat_main.py	Sun Jan 26 18:08:09 2020 +0100
@@ -722,6 +722,7 @@
 
     def isConnected(self, profile_key):
         """Return connection status of profile
+
         @param profile_key: key_word or profile name to determine profile name
         @return: True if connected
         """
--- a/sat/core/xmpp.py	Sat Jan 25 21:08:41 2020 +0100
+++ b/sat/core/xmpp.py	Sun Jan 26 18:08:09 2020 +0100
@@ -345,7 +345,7 @@
         except AttributeError:
             # connection has not been stopped by networkDisabled
             # we don't have to restart it
-            log.debug("no connection to restart")
+            log.debug(f"no connection to restart [{self.profile}]")
             return
         else:
             del self._network_disabled
--- a/sat/plugins/plugin_misc_android.py	Sat Jan 25 21:08:41 2020 +0100
+++ b/sat/plugins/plugin_misc_android.py	Sun Jan 26 18:08:09 2020 +0100
@@ -195,7 +195,9 @@
         # Connectivity handling
         self.cm = activity.getSystemService(Context.CONNECTIVITY_SERVICE)
         self._net_type = None
-        self._checkConnectivity()
+        d = defer.ensureDeferred(self._checkConnectivity())
+        d.addErrback(host.logErrback)
+
         # XXX: we need to keep a reference to BroadcastReceiver to avoid
         #     "XXX has no attribute 'invoke'" error (looks like the same issue as
         #     https://github.com/kivy/pyjnius/issues/59)
@@ -291,12 +293,15 @@
     def _profileAutoconnectGet(self):
         return defer.ensureDeferred(self.profileAutoconnectGet())
 
-    async def profileAutoconnectGet(self):
-        """Return profile to connect automatically by frontend, if any"""
+    async def _getProfilesAutoconnect(self):
         autoconnect_dict = await self.host.memory.storage.getIndParamValues(
             category='Connection', name='autoconnect_backend',
         )
-        profiles_autoconnect = [p for p, v in autoconnect_dict.items() if C.bool(v)]
+        return [p for p, v in autoconnect_dict.items() if C.bool(v)]
+
+    async def profileAutoconnectGet(self):
+        """Return profile to connect automatically by frontend, if any"""
+        profiles_autoconnect = await self._getProfilesAutoconnect()
         if not profiles_autoconnect:
             return None
         if len(profiles_autoconnect) > 1:
@@ -328,19 +333,33 @@
 
     # Connectivity
 
-    def _handleNetworkChange(self, previous, new):
+    async def _handleNetworkChange(self, net_type):
         """Notify the clients about network changes.
 
         This way the client can disconnect/reconnect transport, or change delays
         """
-        if new == NET_TYPE_NONE:
+        log.debug(f"handling network change ({net_type})")
+        if net_type == NET_TYPE_NONE:
             for client in self.host.getClients(C.PROF_KEY_ALL):
                 client.networkDisabled()
-        elif previous == NET_TYPE_NONE:
+        else:
+            # client may be there but disabled (e.g. with stream management)
             for client in self.host.getClients(C.PROF_KEY_ALL):
+                log.debug(f"enabling network for {client.profile}")
                 client.networkEnabled()
 
-    def _checkConnectivity(self):
+            # profiles may have been disconnected and then purged, we try
+            # to reconnect them in case
+            profiles_autoconnect = await self._getProfilesAutoconnect()
+            for profile in profiles_autoconnect:
+                if not self.host.isConnected(profile):
+                    log.info(f"{profile} is not connected, reconnecting it")
+                    try:
+                        await self.host.connect(profile)
+                    except Exception as e:
+                        log.error(f"Can't connect profile {profile}: {e}")
+
+    async def _checkConnectivity(self):
         active_network = self.cm.getActiveNetworkInfo()
         if active_network is None:
             net_type = NET_TYPE_NONE
@@ -352,9 +371,9 @@
                 net_type = NET_TYPE_MOBILE
             else:
                 net_type = NET_TYPE_OTHER
+
         if net_type != self._net_type:
             log.info("connectivity has changed")
-            previous = self._net_type
             self._net_type = net_type
             if net_type == NET_TYPE_NONE:
                 log.info("no network active")
@@ -365,12 +384,16 @@
             else:
                 log.info("network activated (type={net_type_android})"
                     .format(net_type_android=net_type_android))
-            self._handleNetworkChange(previous, net_type)
         else:
             log.debug("_checkConnectivity called without network change ({net_type})"
                 .format(net_type = net_type))
 
+        # we always call _handleNetworkChange even if there is not connectivity change
+        # to be sure to reconnect when necessary
+        await self._handleNetworkChange(net_type)
+
 
     def onConnectivityChange(self):
         log.debug("onConnectivityChange called")
-        self._checkConnectivity()
+        d = defer.ensureDeferred(self._checkConnectivity())
+        d.addErrback(self.host.logErrback)