Send connman mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."


Today's Topics:

   1. [PATCH 1/5] service: Re-add run_vpn_auto_connect() with
      increasing delays to main loop (Jussi Laakkonen)
   2. [PATCH 2/5] service: Indicate service state when autoconnect
      succeeds. (Jussi Laakkonen)
   3. [PATCH 3/5] service: Remove existing VPN auto connect from
      main loop. (Jussi Laakkonen)
   4. [PATCH 4/5] service: Implement a do_auto_connect() to include
      VPNs in autoconnect. (Jussi Laakkonen)
   5. [PATCH 5/5] service: Call vpn_auto_connect() when default
      service changes. (Jussi Laakkonen)


----------------------------------------------------------------------

Message: 1
Date: Tue, 23 Apr 2019 18:22:43 +0300
From: Jussi Laakkonen <[email protected]>
To: [email protected]
Subject: [PATCH 1/5] service: Re-add run_vpn_auto_connect() with
        increasing delays to main loop
Message-ID: <[email protected]>

This commit enhances run_vpn_auto_connect() to re-add itself to main
loop when there are VPNs to auto connect but VPN connection has not
completed yet. The delay will increase at each attempt, which at start
is 0 and is passed along as the user data. The delay will increase after
VPN_AUTOCONNECT_TIMEOUT_STEP attempts (30) with 1s, starting with
default value VPN_AUTOCONNECT_TIMEOUT_DEFAULT (1) that is being set
after the initial call. The value is increased until the threshold
(VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_TRESHOLD, 270) is reached. Delays
longer than 10s are not imposed.

This improves the autoconnection in situations when the network
conditions change rapidly, networks are slow to get online status, there
are lots of repetitive switches between networks and different network
types. If there is no connected default service or the default service
is a connected VPN or there are no VPNs with autoconnect set function is
removed from mainloop.

Connecting VPNs are regarded as autoconnectable to ensure re-connection
of the VPN if the network breaks during connection establishment and new
network is being connected to.
---
 src/service.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 4 deletions(-)

diff --git a/src/service.c b/src/service.c
index 912c6095..aa1b91b8 100644
--- a/src/service.c
+++ b/src/service.c
@@ -39,6 +39,10 @@
 
 #define CONNECT_TIMEOUT                120
 
+#define VPN_AUTOCONNECT_TIMEOUT_DEFAULT 1
+#define VPN_AUTOCONNECT_TIMEOUT_STEP 30
+#define VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_TRESHOLD 270
+
 static DBusConnection *connection = NULL;
 
 static GList *service_list = NULL;
@@ -4206,8 +4210,28 @@ void __connman_service_auto_connect(enum 
connman_service_connect_reason reason)
 static gboolean run_vpn_auto_connect(gpointer data) {
        GList *list;
        bool need_split = false;
+       bool autoconnectable_vpns = false;
+       int attempts = 0;
+       int timeout = VPN_AUTOCONNECT_TIMEOUT_DEFAULT;
+       struct connman_service *def_service;
 
-       vpn_autoconnect_id = 0;
+       attempts = GPOINTER_TO_INT(data);
+       def_service = connman_service_get_default();
+
+       /*
+        * Stop auto connecting VPN if there is no transport service or the
+        * transport service is not connected or if the  current default service
+        * is a connected VPN (in ready state).
+        */
+       if (!def_service || !is_connected(def_service->state) ||
+               (def_service->type == CONNMAN_SERVICE_TYPE_VPN &&
+               is_connected(def_service->state))) {
+
+               DBG("stopped, default service %s connected %d",
+                       def_service ? def_service->identifier : "NULL",
+                       def_service ? is_connected(def_service->state) : -1);
+               goto out;
+       }
 
        for (list = service_list; list; list = list->next) {
                struct connman_service *service = list->data;
@@ -4217,9 +4241,17 @@ static gboolean run_vpn_auto_connect(gpointer data) {
                        continue;
 
                if (is_connected(service->state) ||
-                               is_connecting(service->state)) {
+                                       is_connecting(service->state)) {
                        if (!service->do_split_routing)
                                need_split = true;
+
+                       /*
+                        * If the service is connecting it must be accounted
+                        * for to keep the autoconnection in main loop.
+                        */
+                       if (is_connecting(service->state))
+                               autoconnectable_vpns = true;
+
                        continue;
                }
 
@@ -4237,14 +4269,50 @@ static gboolean run_vpn_auto_connect(gpointer data) {
 
                res = __connman_service_connect(service,
                                CONNMAN_SERVICE_CONNECT_REASON_AUTO);
-               if (res < 0 && res != -EINPROGRESS)
+
+               switch (res) {
+               case 0:
+               case -EINPROGRESS:
+                       autoconnectable_vpns = true;
+                       break;
+               default:
                        continue;
+               }
 
                if (!service->do_split_routing)
                        need_split = true;
        }
 
-       return FALSE;
+       /* Stop if there is no VPN to automatically connect.*/
+       if (!autoconnectable_vpns) {
+               DBG("stopping, no autoconnectable VPNs found");
+               goto out;
+       }
+
+       /* Increase the attempt count up to the treshold.*/
+       if (attempts < VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_TRESHOLD)
+               attempts++;
+
+       /*
+        * Timeout increases with 1s after VPN_AUTOCONNECT_TIMEOUT_STEP amount
+        * of attempts made. After VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_TRESHOLD is
+        * reached the delay does not increase.
+        */
+       timeout = timeout + (int)(attempts / VPN_AUTOCONNECT_TIMEOUT_STEP);
+
+       /* Re add this to main loop */
+       vpn_autoconnect_id =
+               g_timeout_add_seconds(timeout, run_vpn_auto_connect,
+                       GINT_TO_POINTER(attempts));
+
+       DBG("re-added to main loop, next VPN autoconnect in %d seconds (#%d)",
+               timeout, attempts);
+
+       return G_SOURCE_REMOVE;
+
+out:
+       vpn_autoconnect_id = 0;
+       return G_SOURCE_REMOVE;
 }
 
 static void vpn_auto_connect(void)
-- 
2.20.1



------------------------------

Message: 2
Date: Tue, 23 Apr 2019 18:22:44 +0300
From: Jussi Laakkonen <[email protected]>
To: [email protected]
Subject: [PATCH 2/5] service: Indicate service state when autoconnect
        succeeds.
Message-ID: <[email protected]>

This commit sets service.c to indicate service state in case the service
is being autoconnected and connection attempt succeeds immediately.
Connecting provider or network do not forward the service state changes
and this makes it impossible for, e.g, plugins/vpn.c to keep track of
when the service/list/default changes. Same applies with service
autoconnect and may result in improperly updated DNS servers.

These issues happen usually when changing between different types of
networks while having a VPN autoconnection set. In some cases VPN
disconnection detection is not working or all of the DNS servers will
remain disabled.
---
 src/service.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/service.c b/src/service.c
index aa1b91b8..4697b055 100644
--- a/src/service.c
+++ b/src/service.c
@@ -4101,6 +4101,8 @@ static bool autoconnect_already_connecting(struct 
connman_service *service,
        return false;
 }
 
+static int service_indicate_state(struct connman_service *service);
+
 static bool auto_connect_service(GList *services,
                                enum connman_service_connect_reason reason,
                                bool preferred)
@@ -4159,7 +4161,8 @@ static bool auto_connect_service(GList *services,
                DBG("service %p %s %s", service, service->name,
                        (preferred) ? "preferred" : reason2string(reason));
 
-               __connman_service_connect(service, reason);
+               if (__connman_service_connect(service, reason) == 0)
+                       service_indicate_state(service);
 
                if (autoconnect_no_session_active(service))
                        return true;
@@ -4272,6 +4275,7 @@ static gboolean run_vpn_auto_connect(gpointer data) {
 
                switch (res) {
                case 0:
+                       service_indicate_state(service);
                case -EINPROGRESS:
                        autoconnectable_vpns = true;
                        break;
-- 
2.20.1



------------------------------

Message: 3
Date: Tue, 23 Apr 2019 18:22:45 +0300
From: Jussi Laakkonen <[email protected]>
To: [email protected]
Subject: [PATCH 3/5] service: Remove existing VPN auto connect from
        main loop.
Message-ID: <[email protected]>

To ensure better autoconnect for VPNs in case there is a network change
remove the existing autoconnect from main loop. Otherwise it may be that
VPN autoconnect would be still running with 10s delays blocking the
re-connection after new network has become online.
---
 src/service.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/service.c b/src/service.c
index 4697b055..388f6134 100644
--- a/src/service.c
+++ b/src/service.c
@@ -4321,8 +4321,16 @@ out:
 
 static void vpn_auto_connect(void)
 {
-       if (vpn_autoconnect_id)
-               return;
+       /*
+        * Remove existing autoconnect from main loop to reset the attempt
+        * counter in order to get VPN connected when there is a network change.
+        */
+       if (vpn_autoconnect_id) {
+               if (!g_source_remove(vpn_autoconnect_id)) {
+                       DBG("cannot remove VPN autoconnect from main loop");
+                       return;
+               }
+       }
 
        vpn_autoconnect_id =
                g_idle_add(run_vpn_auto_connect, NULL);
-- 
2.20.1



------------------------------

Message: 4
Date: Tue, 23 Apr 2019 18:22:46 +0300
From: Jussi Laakkonen <[email protected]>
To: [email protected]
Subject: [PATCH 4/5] service: Implement a do_auto_connect() to include
        VPNs in autoconnect.
Message-ID: <[email protected]>

This commit adds a function to include VPNs in service.c internal
autoconnect processes. For other than VPN services it calls
__connman_service_auto_connect(), use of which is replaced with use of
do_auto_connect() in service.c, and with VPNs vpn_auto_connect() is
called. Main reason is that VPN autoconnection is not working with
run_auto_connect() and must be triggered with this kind of approach.

For VPNs connection reason has to be set as user/auto. VPNs should not
be kept reconnecting if the VPN is in failure state, unless the user has
requested a connection. In case the network conditions cause the failure
other autoconnection mechanisms do trigger re-connection of VPN, which
rely on correct state reporting from connman-vpnd.
---
 src/service.c | 47 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/src/service.c b/src/service.c
index 388f6134..ea6246d5 100644
--- a/src/service.c
+++ b/src/service.c
@@ -148,6 +148,7 @@ static struct connman_ipconfig *create_ip4config(struct 
connman_service *service
 static struct connman_ipconfig *create_ip6config(struct connman_service 
*service,
                int index);
 static void dns_changed(struct connman_service *service);
+static void vpn_auto_connect(void);
 
 struct find_data {
        const char *path;
@@ -3413,6 +3414,38 @@ error:
        return -EINVAL;
 }
 
+static void do_auto_connect(struct connman_service *service,
+       enum connman_service_connect_reason reason)
+{
+       /*
+        * CONNMAN_SERVICE_CONNECT_REASON_NONE must be ignored for VPNs. VPNs
+        * always have reason CONNMAN_SERVICE_CONNECT_REASON_USER/AUTO.
+        */
+       if (!service || (service->type == CONNMAN_SERVICE_TYPE_VPN &&
+               reason == CONNMAN_SERVICE_CONNECT_REASON_NONE))
+               return;
+
+       /*
+        * Run service auto connect when a service is changed. This is not
+        * needed to be run when VPN service changes, then vpn auto connect is
+        * sufficient.
+        *
+        * Do not run vpn_auto_connect() when VPN entering failure state
+        * triggers this via service_complete() that is called for each service
+        * that is set to failure state in service_indicate_state(). Otherwise
+        * the timeout of vpn_auto_connect() will be reset and the delays for
+        * VPN connections are reset likewise. User request should reset the
+        * timer.
+        */
+       if (service->type != CONNMAN_SERVICE_TYPE_VPN)
+               __connman_service_auto_connect(reason);
+       else if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
+               reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
+               return;
+
+       vpn_auto_connect();
+}
+
 int __connman_service_reset_ipconfig(struct connman_service *service,
                enum connman_ipconfig_type type, DBusMessageIter *array,
                enum connman_service_state *new_state)
@@ -3477,7 +3510,7 @@ int __connman_service_reset_ipconfig(struct 
connman_service *service,
                settings_changed(service, new_ipconfig);
                address_updated(service, type);
 
-               
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+               do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
        }
 
        DBG("err %d ipconfig %p type %d method %d state %s", err,
@@ -3555,7 +3588,8 @@ static DBusMessage *set_property(DBusConnection *conn,
                autoconnect_changed(service);
 
                if (autoconnect)
-                       
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+                       do_auto_connect(service,
+                                       CONNMAN_SERVICE_CONNECT_REASON_AUTO);
 
                service_save(service);
        } else if (g_str_equal(name, "Nameservers.Configuration")) {
@@ -3881,7 +3915,7 @@ static void service_complete(struct connman_service 
*service)
        reply_pending(service, EIO);
 
        if (service->connect_reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
-               __connman_service_auto_connect(service->connect_reason);
+               do_auto_connect(service, service->connect_reason);
 
        g_get_current_time(&service->modified);
        service_save(service);
@@ -4433,7 +4467,7 @@ static gboolean connect_timeout(gpointer user_data)
        if (autoconnect &&
                        service->connect_reason !=
                                CONNMAN_SERVICE_CONNECT_REASON_USER)
-               
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+               do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
 
        return FALSE;
 }
@@ -5937,7 +5971,7 @@ static int service_indicate_state(struct connman_service 
*service)
                 */
                downgrade_connected_services();
 
-               
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+               do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
                break;
 
        case CONNMAN_SERVICE_STATE_FAILURE:
@@ -7288,7 +7322,8 @@ struct connman_service * 
__connman_service_create_from_network(struct connman_ne
                        case CONNMAN_SERVICE_TYPE_VPN:
                        case CONNMAN_SERVICE_TYPE_WIFI:
                        case CONNMAN_SERVICE_TYPE_CELLULAR:
-                               
__connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+                               do_auto_connect(service,
+                                       CONNMAN_SERVICE_CONNECT_REASON_AUTO);
                                break;
                        }
                }
-- 
2.20.1



------------------------------

Message: 5
Date: Tue, 23 Apr 2019 18:22:47 +0300
From: Jussi Laakkonen <[email protected]>
To: [email protected]
Subject: [PATCH 5/5] service: Call vpn_auto_connect() when default
        service changes.
Message-ID: <[email protected]>

This commit adds call to vpn_auto_connect() when default service changes
and the service is not a VPN service. With this change it is ensured
that VPNs are being autoconnected when the default network changes.
---
 src/service.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/service.c b/src/service.c
index ea6246d5..50238e3e 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1594,6 +1594,16 @@ static void default_changed(void)
                if (service->domainname &&
                                
connman_setting_get_bool("AllowDomainnameUpdates"))
                        __connman_utsname_set_domainname(service->domainname);
+
+               /*
+                * Connect VPN automatically when new default service
+                * is set and connected, unless new default is VPN
+                */
+               if (is_connected(service->state) &&
+                       service->type != CONNMAN_SERVICE_TYPE_VPN) {
+                       DBG("running vpn_auto_connect");
+                       vpn_auto_connect();
+               }
        }
 
        __connman_notifier_default_changed(service);
-- 
2.20.1



------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman


------------------------------

End of connman Digest, Vol 42, Issue 17
***************************************

Reply via email to