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