From: Daniel Wagner <[email protected]>

When Session.Disconnect() is called, only services which are not
activily used by any other session will be disconnected.

The free ride session are not counted.
---
 src/session.c |  116 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 101 insertions(+), 15 deletions(-)

diff --git a/src/session.c b/src/session.c
index a125dd8..ae7cf09 100644
--- a/src/session.c
+++ b/src/session.c
@@ -43,6 +43,13 @@ enum connman_session_trigger {
        CONNMAN_SESSION_TRIGGER_ECALL           = 6,
 };
 
+enum connman_session_reason {
+       CONNMAN_SESSION_REASON_UNKNOWN          = 0,
+       CONNMAN_SESSION_REASON_CONNECT          = 1,
+       CONNMAN_SESSION_REASON_FREE_RIDE        = 2,
+       CONNMAN_SESSION_REASON_PERIODIC         = 3,
+};
+
 enum connman_session_roaming_policy {
        CONNMAN_SESSION_ROAMING_POLICY_UNKNOWN          = 0,
        CONNMAN_SESSION_ROAMING_POLICY_DEFAULT          = 1,
@@ -67,6 +74,8 @@ struct session_info {
        enum connman_session_roaming_policy roaming_policy;
        unsigned int marker;
 
+       /* track why this service was selected */
+       enum connman_session_reason reason;
        struct connman_service *service;
 };
 
@@ -112,6 +121,22 @@ static const char *trigger2string(enum 
connman_session_trigger trigger)
        return NULL;
 }
 
+static const char *reason2string(enum connman_session_reason reason)
+{
+       switch (reason) {
+       case CONNMAN_SESSION_REASON_UNKNOWN:
+               break;
+       case CONNMAN_SESSION_REASON_CONNECT:
+               return "connect";
+       case CONNMAN_SESSION_REASON_FREE_RIDE:
+               return "free-ride";
+       case CONNMAN_SESSION_REASON_PERIODIC:
+               return "periodic";
+       }
+
+       return NULL;
+}
+
 static const char *roamingpolicy2string(enum connman_session_roaming_policy 
policy)
 {
        switch (policy) {
@@ -732,14 +757,59 @@ static void update_info(struct session_info *info)
        }
 }
 
+static connman_bool_t explicit_connect(enum connman_session_reason reason)
+{
+       switch (reason) {
+       case CONNMAN_SESSION_REASON_UNKNOWN:
+       case CONNMAN_SESSION_REASON_FREE_RIDE:
+               break;
+       case CONNMAN_SESSION_REASON_CONNECT:
+       case CONNMAN_SESSION_REASON_PERIODIC:
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static int count_service_usage(struct connman_session *session)
+{
+       struct session_info *info = &session->info;
+       struct session_info *info_iter;
+       struct connman_session *session_iter;
+       GHashTableIter iter;
+       gpointer key, value;
+       int count = 0;
+
+       g_hash_table_iter_init(&iter, session_hash);
+
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               session_iter = value;
+               info_iter = &session_iter->info;
+
+               if (session == session_iter)
+                       continue;
+
+               if (info->service != info_iter->service)
+                       continue;
+
+               if (explicit_connect(info_iter->reason) == FALSE)
+                       continue;
+
+               count++;
+       }
+
+       return count;
+}
+
 static void select_and_connect(struct connman_session *session,
-                               connman_bool_t do_connect)
+                               enum connman_session_reason reason)
 {
        struct session_info *info = &session->info;
        struct connman_service *service = NULL;
        GSequenceIter *iter;
+       connman_bool_t do_connect = FALSE;
 
-       DBG("session %p connect %d", session, do_connect);
+       DBG("session %p reason %s", session, reason2string(reason));
 
        iter = g_sequence_get_begin_iter(session->service_list);
 
@@ -752,7 +822,8 @@ static void select_and_connect(struct connman_session 
*session,
                }
 
                if (__connman_service_is_idle(service) == TRUE &&
-                               do_connect == TRUE) {
+                               explicit_connect(reason) == TRUE) {
+                       do_connect = TRUE;
                        break;
                }
 
@@ -763,10 +834,12 @@ static void select_and_connect(struct connman_session 
*session,
 
        if (info->service != NULL && info->service != service) {
                __connman_service_disconnect(info->service);
+               info->reason = CONNMAN_SESSION_REASON_UNKNOWN;
                info->service = NULL;
        }
 
        if (service != NULL) {
+               info->reason = reason;
                info->service = service;
 
                if (do_connect == TRUE)
@@ -806,30 +879,38 @@ static void session_changed(struct connman_session 
*session,
                        }
                }
 
-               /* Try to free ride */
-               if (info->online == FALSE)
-                       select_and_connect(session, FALSE);
+               if (info->online == FALSE) {
+                       select_and_connect(session,
+                                       CONNMAN_SESSION_REASON_FREE_RIDE);
+               }
 
                break;
        case CONNMAN_SESSION_TRIGGER_CONNECT:
-               if (info->online == TRUE)
+               if (info->online == TRUE) {
+                       info->reason = CONNMAN_SESSION_REASON_CONNECT;
                        break;
+               }
 
-               select_and_connect(session, TRUE);
+               select_and_connect(session,
+                               CONNMAN_SESSION_REASON_CONNECT);
 
                break;
        case CONNMAN_SESSION_TRIGGER_DISCONNECT:
                if (info->online == FALSE)
                        break;
 
-               if (info->service != NULL)
-                       __connman_service_disconnect(info->service);
+               if (info->service != NULL) {
+                       if (count_service_usage(session) == 0)
+                               __connman_service_disconnect(info->service);
+               }
 
+               info->reason = CONNMAN_SESSION_REASON_UNKNOWN;
                info->service = NULL;
 
                break;
        case CONNMAN_SESSION_TRIGGER_PERIODIC:
-               select_and_connect(session, TRUE);
+               select_and_connect(session,
+                               CONNMAN_SESSION_REASON_PERIODIC);
 
                break;
        case CONNMAN_SESSION_TRIGGER_SERVICE:
@@ -838,18 +919,21 @@ static void session_changed(struct connman_session 
*session,
 
                if (info->stay_connected == TRUE) {
                        DBG("StayConnected");
-                       select_and_connect(session, TRUE);
+                       select_and_connect(session,
+                                       CONNMAN_SESSION_REASON_CONNECT);
 
                        break;
                }
 
-               /* Try to free ride */
-               select_and_connect(session, FALSE);
+               select_and_connect(session,
+                               CONNMAN_SESSION_REASON_FREE_RIDE);
 
                break;
        case CONNMAN_SESSION_TRIGGER_ECALL:
-               if (info->online == FALSE && info->service != NULL)
+               if (info->online == FALSE && info->service != NULL) {
+                       info->reason = CONNMAN_SESSION_REASON_UNKNOWN;
                        info->service = NULL;
+               }
 
                break;
        }
@@ -1227,6 +1311,7 @@ int __connman_session_create(DBusMessage *msg)
        info->roaming_policy = roaming_policy;
        info->service = NULL;
        info->marker = 0;
+       info->reason = CONNMAN_SESSION_REASON_UNKNOWN;
 
        if (allowed_bearers == NULL) {
                info->allowed_bearers =
@@ -1279,6 +1364,7 @@ int __connman_session_create(DBusMessage *msg)
        info_last->roaming_policy = info->roaming_policy;
        info_last->service = info->service;
        info_last->marker = info->marker;
+       info_last->reason = info->reason;
        info_last->allowed_bearers = info->allowed_bearers;
        update_info(info_last);
 
-- 
1.7.4.4

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to