From: Daniel Wagner <daniel.wag...@bmw-carit.de>

The current implemention is decoupled from what
service.c is doing. For example session.c needs to
guess via the service state which session original
wanted a connection. Let's start over with a
new approach. First step is to remove the current
implemantation.
---
 src/session.c | 573 +---------------------------------------------------------
 1 file changed, 10 insertions(+), 563 deletions(-)

diff --git a/src/session.c b/src/session.c
index 5985a59..e4a8b49 100644
--- a/src/session.c
+++ b/src/session.c
@@ -39,15 +39,6 @@ static GSList *policy_list;
 static uint32_t session_mark = 256;
 static struct firewall_context *global_firewall = NULL;
 
-enum connman_session_trigger {
-       CONNMAN_SESSION_TRIGGER_UNKNOWN         = 0,
-       CONNMAN_SESSION_TRIGGER_SETTING         = 1,
-       CONNMAN_SESSION_TRIGGER_CONNECT         = 2,
-       CONNMAN_SESSION_TRIGGER_DISCONNECT      = 3,
-       CONNMAN_SESSION_TRIGGER_SERVICE         = 4,
-       CONNMAN_SESSION_TRIGGER_ECALL           = 5,
-};
-
 enum connman_session_reason {
        CONNMAN_SESSION_REASON_UNKNOWN          = 0,
        CONNMAN_SESSION_REASON_CONNECT          = 1,
@@ -90,31 +81,8 @@ struct connman_session {
        uint32_t mark;
        int index;
        char *gateway;
-
-       GList *service_list;
-       GHashTable *service_hash;
 };
 
-static const char *trigger2string(enum connman_session_trigger trigger)
-{
-       switch (trigger) {
-       case CONNMAN_SESSION_TRIGGER_UNKNOWN:
-               break;
-       case CONNMAN_SESSION_TRIGGER_SETTING:
-               return "setting";
-       case CONNMAN_SESSION_TRIGGER_CONNECT:
-               return "connect";
-       case CONNMAN_SESSION_TRIGGER_DISCONNECT:
-               return "disconnect";
-       case CONNMAN_SESSION_TRIGGER_SERVICE:
-               return "service";
-       case CONNMAN_SESSION_TRIGGER_ECALL:
-               return "ecall";
-       }
-
-       return NULL;
-}
-
 static const char *reason2string(enum connman_session_reason reason)
 {
        switch (reason) {
@@ -482,9 +450,6 @@ static void cleanup_session_final(struct connman_session 
*session)
                                session->info->config.allowed_bearers);
 
        g_slist_free(session->user_allowed_bearers);
-       if (session->service_hash)
-               g_hash_table_destroy(session->service_hash);
-       g_list_free(session->service_list);
 
        free_session(session);
 }
@@ -921,30 +886,6 @@ static void append_notify(DBusMessageIter *dict,
        session->append_all = false;
 }
 
-static bool is_type_matching_state(enum connman_session_state *state,
-                                               enum connman_session_type type)
-{
-       switch (type) {
-       case CONNMAN_SESSION_TYPE_UNKNOWN:
-               return false;
-       case CONNMAN_SESSION_TYPE_ANY:
-               return true;
-       case CONNMAN_SESSION_TYPE_LOCAL:
-               if (*state >= CONNMAN_SESSION_STATE_CONNECTED) {
-                       *state = CONNMAN_SESSION_STATE_CONNECTED;
-                       return true;
-               }
-
-               break;
-       case CONNMAN_SESSION_TYPE_INTERNET:
-               if (*state == CONNMAN_SESSION_STATE_ONLINE)
-                       return true;
-               break;
-       }
-
-       return false;
-}
-
 static bool compute_notifiable_changes(struct connman_session *session)
 {
        struct session_info *info_last = session->info_last;
@@ -1011,200 +952,6 @@ static void ipconfig_ipv6_changed(struct connman_session 
*session)
                                                session->service);
 }
 
-static bool service_type_match(struct connman_session *session,
-                                       struct connman_service *service)
-{
-       struct session_info *info = session->info;
-       GSList *list;
-
-       for (list = info->config.allowed_bearers;
-                       list; list = list->next) {
-               enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
-               enum connman_service_type service_type;
-
-               if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN)
-                       return true;
-
-               service_type = connman_service_get_type(service);
-               if (bearer == service_type)
-                       return true;
-       }
-
-       return false;
-}
-
-static bool service_match(struct connman_session *session,
-                                       struct connman_service *service)
-{
-       if (!service_type_match(session, service))
-               return false;
-
-       return true;
-}
-
-static int service_type_weight(enum connman_service_type type)
-{
-       /*
-        * The session doesn't care which service
-        * to use. Nevertheless we have to sort them
-        * according their type. The ordering is
-        *
-        * 1. Ethernet
-        * 2. Bluetooth
-        * 3. WiFi
-        * 4. Cellular
-        */
-
-       switch (type) {
-       case CONNMAN_SERVICE_TYPE_ETHERNET:
-               return 4;
-       case CONNMAN_SERVICE_TYPE_BLUETOOTH:
-               return 3;
-       case CONNMAN_SERVICE_TYPE_WIFI:
-               return 2;
-       case CONNMAN_SERVICE_TYPE_CELLULAR:
-               return 1;
-       case CONNMAN_SERVICE_TYPE_UNKNOWN:
-       case CONNMAN_SERVICE_TYPE_SYSTEM:
-       case CONNMAN_SERVICE_TYPE_GPS:
-       case CONNMAN_SERVICE_TYPE_VPN:
-       case CONNMAN_SERVICE_TYPE_GADGET:
-               break;
-       }
-
-       return 0;
-}
-
-static gint sort_allowed_bearers(struct connman_service *service_a,
-                                       struct connman_service *service_b,
-                                       struct connman_session *session)
-{
-       struct session_info *info = session->info;
-       GSList *list;
-       enum connman_service_type type_a, type_b;
-       int weight_a, weight_b;
-
-       type_a = connman_service_get_type(service_a);
-       type_b = connman_service_get_type(service_b);
-
-       for (list = info->config.allowed_bearers;
-                       list; list = list->next) {
-               enum connman_service_type bearer = GPOINTER_TO_INT(list->data);
-
-               if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN) {
-                       if (type_a != type_b) {
-                               weight_a = service_type_weight(type_a);
-                               weight_b = service_type_weight(type_b);
-
-                               if (weight_a > weight_b)
-                                       return -1;
-
-                               if (weight_a < weight_b)
-                                       return 1;
-
-                               return 0;
-                       }
-               }
-
-               if (type_a == bearer && type_b == bearer)
-                       return 0;
-
-               if (type_a == bearer && type_b != bearer)
-                       return -1;
-
-               if (type_a != bearer && type_b == bearer)
-                       return 1;
-       }
-
-       return 0;
-}
-
-static gint sort_services(gconstpointer a, gconstpointer b, gpointer user_data)
-{
-       struct connman_service *service_a = (void *)a;
-       struct connman_service *service_b = (void *)b;
-       struct connman_session *session = user_data;
-
-       return sort_allowed_bearers(service_a, service_b, session);
-}
-
-static enum connman_session_state service_to_session_state(enum 
connman_service_state state)
-{
-       switch (state) {
-       case CONNMAN_SERVICE_STATE_UNKNOWN:
-       case CONNMAN_SERVICE_STATE_IDLE:
-       case CONNMAN_SERVICE_STATE_ASSOCIATION:
-       case CONNMAN_SERVICE_STATE_CONFIGURATION:
-       case CONNMAN_SERVICE_STATE_DISCONNECT:
-       case CONNMAN_SERVICE_STATE_FAILURE:
-               break;
-       case CONNMAN_SERVICE_STATE_READY:
-               return CONNMAN_SESSION_STATE_CONNECTED;
-       case CONNMAN_SERVICE_STATE_ONLINE:
-               return CONNMAN_SESSION_STATE_ONLINE;
-       }
-
-       return CONNMAN_SESSION_STATE_DISCONNECTED;
-}
-
-static bool is_connected(enum connman_service_state state)
-{
-       switch (state) {
-       case CONNMAN_SERVICE_STATE_UNKNOWN:
-       case CONNMAN_SERVICE_STATE_IDLE:
-       case CONNMAN_SERVICE_STATE_ASSOCIATION:
-       case CONNMAN_SERVICE_STATE_CONFIGURATION:
-       case CONNMAN_SERVICE_STATE_DISCONNECT:
-       case CONNMAN_SERVICE_STATE_FAILURE:
-               break;
-       case CONNMAN_SERVICE_STATE_READY:
-       case CONNMAN_SERVICE_STATE_ONLINE:
-               return true;
-       }
-
-       return false;
-}
-
-static bool is_connecting(enum connman_service_state state)
-{
-       switch (state) {
-       case CONNMAN_SERVICE_STATE_UNKNOWN:
-       case CONNMAN_SERVICE_STATE_IDLE:
-               break;
-       case CONNMAN_SERVICE_STATE_ASSOCIATION:
-       case CONNMAN_SERVICE_STATE_CONFIGURATION:
-               return true;
-       case CONNMAN_SERVICE_STATE_DISCONNECT:
-       case CONNMAN_SERVICE_STATE_FAILURE:
-       case CONNMAN_SERVICE_STATE_READY:
-       case CONNMAN_SERVICE_STATE_ONLINE:
-               break;
-       }
-
-       return false;
-}
-
-static bool is_disconnected(enum connman_service_state state)
-{
-       if (is_connected(state) || is_connecting(state))
-               return false;
-
-       return true;
-}
-
-static bool 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:
-               return true;
-       }
-
-       return false;
-}
-
 static void deselect_and_disconnect(struct connman_session *session)
 {
        struct session_info *info = session->info;
@@ -1214,70 +961,13 @@ static void deselect_and_disconnect(struct 
connman_session *session)
                                info->config.allowed_bearers);
 
        info->reason = CONNMAN_SESSION_REASON_FREE_RIDE;
-
        info->state = CONNMAN_SESSION_STATE_DISCONNECTED;
-
-       if (!session->service)
-               return;
-
-       session->service = NULL;
-
-       update_routing_table(session);
-}
-
-static void select_connected_service(struct connman_session *session,
-                                       struct connman_service *service)
-{
-       struct session_info *info = session->info;
-       enum connman_service_state service_state;
-       enum connman_session_state state;
-
-       service_state = __connman_service_get_state(service);
-       state = service_to_session_state(service_state);
-       if (!is_type_matching_state(&state, info->config.type))
-               return;
-
-       info->state = state;
-
-       session->service = service;
-}
-
-static void select_offline_service(struct connman_session *session,
-                                       struct connman_service *service)
-{
-       struct session_info *info = session->info;
-       enum connman_service_state service_state;
-
-       if (!explicit_connect(info->reason))
-               return;
-
-       service_state = __connman_service_get_state(service);
-       info->state = service_to_session_state(service_state);
-
-       session->service = service;
-}
-
-static void select_service(struct connman_session *session,
-                               struct connman_service *service)
-{
-       enum connman_service_state service_state;
-
-       DBG("service %p", service);
-
-       service_state = __connman_service_get_state(service);
-       if (is_connected(service_state))
-               select_connected_service(session, service);
-       else
-               select_offline_service(session, service);
 }
 
 static void select_and_connect(struct connman_session *session,
                                enum connman_session_reason reason)
 {
        struct session_info *info = session->info;
-       struct connman_service *service = NULL;
-       enum connman_service_state service_state;
-       GList *list;
 
        DBG("session %p reason %s", session, reason2string(reason));
 
@@ -1290,184 +980,6 @@ static void select_and_connect(struct connman_session 
*session,
        }
 
        info->reason = reason;
-
-       for (list = session->service_list; list; list = list->next) {
-               service = list->data;
-
-               service_state = __connman_service_get_state(service);
-               switch (service_state) {
-               case CONNMAN_SERVICE_STATE_ASSOCIATION:
-               case CONNMAN_SERVICE_STATE_CONFIGURATION:
-               case CONNMAN_SERVICE_STATE_READY:
-               case CONNMAN_SERVICE_STATE_ONLINE:
-               case CONNMAN_SERVICE_STATE_IDLE:
-               case CONNMAN_SERVICE_STATE_DISCONNECT:
-                       select_service(session, service);
-                       update_routing_table(session);
-                       return;
-               case CONNMAN_SERVICE_STATE_UNKNOWN:
-               case CONNMAN_SERVICE_STATE_FAILURE:
-                       break;
-               }
-       }
-}
-
-static void iterate_service_cb(struct connman_service *service,
-                               void *user_data)
-{
-       struct connman_session *session = user_data;
-       enum connman_service_state service_state;
-
-       service_state = __connman_service_get_state(service);
-       if (!is_connected(service_state))
-               return;
-
-       if (!service_match(session, service))
-               return;
-
-       g_hash_table_replace(session->service_hash, service, NULL);
-}
-
-static void populate_service_list(struct connman_session *session)
-{
-       GHashTableIter iter;
-       gpointer key, value;
-
-       session->service_hash =
-               g_hash_table_new_full(g_direct_hash, g_direct_equal,
-                                       NULL, NULL);
-       __connman_service_iterate_services(iterate_service_cb, session);
-
-       g_hash_table_iter_init(&iter, session->service_hash);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               struct connman_service *service = key;
-
-               DBG("service %p type %s name %s", service,
-                       service2bearer(connman_service_get_type(service)),
-                       __connman_service_get_name(service));
-               session->service_list = g_list_prepend(session->service_list,
-                                                       service);
-       }
-
-       session->service_list = g_list_sort_with_data(session->service_list,
-                                               sort_services, session);
-}
-
-static void session_changed(struct connman_session *session,
-                               enum connman_session_trigger trigger)
-{
-       struct session_info *info = session->info;
-       struct session_info *info_last = session->info_last;
-       struct connman_service *service = NULL, *service_last = NULL;
-       enum connman_service_state service_state;
-       GHashTable *service_hash_last;
-
-       /*
-        * TODO: This only a placeholder for the 'real' algorithm to
-        * play a bit around. So we are going to improve it step by step.
-        */
-
-       DBG("session %p trigger %s reason %s", session, trigger2string(trigger),
-                                               reason2string(info->reason));
-
-
-       if (session->service) {
-               enum connman_session_state state;
-
-               service_state = __connman_service_get_state(session->service);
-               state = service_to_session_state(service_state);
-
-               if (is_type_matching_state(&state, info->config.type))
-                       info->state = state;
-       }
-
-       switch (trigger) {
-       case CONNMAN_SESSION_TRIGGER_UNKNOWN:
-               DBG("ignore session changed event");
-               return;
-       case CONNMAN_SESSION_TRIGGER_SETTING:
-               if (info->config.allowed_bearers != 
info_last->config.allowed_bearers) {
-
-                       service_hash_last = session->service_hash;
-                       g_list_free(session->service_list);
-                       session->service_list = NULL;
-
-                       service = session->service;
-
-                       populate_service_list(session);
-
-                       if (service) {
-                               service_last = g_hash_table_lookup(
-                                                       service_hash_last,
-                                                       service);
-                       }
-
-                       if (service_last &&
-                               !g_hash_table_lookup(session->service_hash,
-                                                       service)) {
-
-                               /*
-                                * The currently selected service is
-                                * not part of this session anymore.
-                                */
-                               deselect_and_disconnect(session);
-                       }
-
-                       g_hash_table_destroy(service_hash_last);
-               }
-
-               if (info->config.type != info_last->config.type) {
-                       if (info->state >= CONNMAN_SESSION_STATE_CONNECTED &&
-                                       !is_type_matching_state(&info->state,
-                                                       info->config.type))
-                               deselect_and_disconnect(session);
-               }
-
-               if (info->state == CONNMAN_SESSION_STATE_DISCONNECTED) {
-                       select_and_connect(session,
-                                       CONNMAN_SESSION_REASON_FREE_RIDE);
-               }
-
-               break;
-       case CONNMAN_SESSION_TRIGGER_ECALL:
-               /*
-                * For the time beeing we fallback to normal connect
-                * strategy.
-                */
-       case CONNMAN_SESSION_TRIGGER_CONNECT:
-               if (info->state >= CONNMAN_SESSION_STATE_CONNECTED)
-                       break;
-
-               if (session->service) {
-                       service_state = __connman_service_get_state(
-                                               session->service);
-                       if (is_connecting(service_state))
-                               break;
-               }
-
-               select_and_connect(session, CONNMAN_SESSION_REASON_CONNECT);
-
-               break;
-       case CONNMAN_SESSION_TRIGGER_DISCONNECT:
-               deselect_and_disconnect(session);
-
-               break;
-       case CONNMAN_SESSION_TRIGGER_SERVICE:
-               if (session->service) {
-                       service_state = __connman_service_get_state(
-                                               session->service);
-                       if (is_connecting(service_state) ||
-                               is_connected(service_state))
-                       break;
-               }
-
-               select_and_connect(session, info->reason);
-
-               break;
-       }
-
-       session_notify(session);
 }
 
 int connman_session_config_update(struct connman_session *session)
@@ -1524,7 +1036,7 @@ int connman_session_config_update(struct connman_session 
*session)
 
        info->config.priority = session->policy_config->priority;
 
-       session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING);
+       session_notify(session);
 
        return 0;
 }
@@ -1541,9 +1053,9 @@ static DBusMessage *connect_session(DBusConnection *conn,
                        return __connman_error_failed(msg, EBUSY);
 
                session->ecall = true;
-               session_changed(session, CONNMAN_SESSION_TRIGGER_ECALL);
-       } else
-               session_changed(session, CONNMAN_SESSION_TRIGGER_CONNECT);
+       }
+
+       select_and_connect(session, CONNMAN_SESSION_REASON_CONNECT);
 
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
@@ -1562,7 +1074,7 @@ static DBusMessage *disconnect_session(DBusConnection 
*conn,
                session->ecall = false;
        }
 
-       session_changed(session, CONNMAN_SESSION_TRIGGER_DISCONNECT);
+       deselect_and_disconnect(session);
 
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
@@ -1637,7 +1149,7 @@ static DBusMessage *change_session(DBusConnection *conn,
                goto err;
        }
 
-       session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING);
+       session_notify(session);
 
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 
@@ -1785,8 +1297,6 @@ static int session_create_final(struct creation_data 
*creation_data,
        g_dbus_send_message(connection, reply);
        creation_data->pending = NULL;
 
-       populate_service_list(session);
-
        info_last->state = info->state;
        info_last->config.priority = info->config.priority;
        info_last->config.roaming_policy = info->config.roaming_policy;
@@ -1794,7 +1304,7 @@ static int session_create_final(struct creation_data 
*creation_data,
 
        session->append_all = true;
 
-       session_changed(session, CONNMAN_SESSION_TRIGGER_SETTING);
+       session_notify(session);
 
        cleanup_creation_data(creation_data);
 
@@ -2104,75 +1614,10 @@ int __connman_session_destroy(DBusMessage *msg)
        return 0;
 }
 
-static void service_add(struct connman_service *service, const char *name)
-{
-       GHashTableIter iter;
-       gpointer key, value;
-       struct connman_session *session;
-
-       DBG("service %p", service);
-
-       g_hash_table_iter_init(&iter, session_hash);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               session = value;
-
-               if (!service_match(session, service))
-                       continue;
-
-               if (g_hash_table_lookup(session->service_hash, service)) {
-                       session->service_list =
-                               g_list_sort_with_data(session->service_list,
-                                               sort_services, session);
-               } else {
-                       session->service_list =
-                               g_list_insert_sorted_with_data(
-                               session->service_list, service,
-                               sort_services, session);
-
-                       g_hash_table_replace(session->service_hash,
-                                               service, service);
-               }
-
-               session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
-       }
-}
-
-static void service_remove(struct connman_service *service)
-{
-       GHashTableIter iter;
-       gpointer key, value;
-
-       DBG("service %p", service);
-
-       g_hash_table_iter_init(&iter, session_hash);
-
-       while (g_hash_table_iter_next(&iter, &key, &value)) {
-               struct connman_session *session = value;
-
-               if (!g_hash_table_lookup(session->service_hash, service))
-                       continue;
-
-               session->service_list = g_list_remove(session->service_list,
-                                                       service);
-
-               g_hash_table_remove(session->service_hash, service);
-
-               if (session->service && session->service == service)
-                       session->service = NULL;
-               session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
-       }
-}
-
 static void service_state_changed(struct connman_service *service,
-                                       enum connman_service_state state)
+                               enum connman_service_state state)
 {
        DBG("service %p state %d", service, state);
-
-       if (is_connected(state))
-               service_add(service, __connman_service_get_name(service));
-       else if (is_disconnected(state))
-               service_remove(service);
 }
 
 static void ipconfig_changed(struct connman_service *service,
@@ -2198,6 +1643,8 @@ static void ipconfig_changed(struct connman_service 
*service,
                        continue;
 
                if (session->service && session->service == service) {
+                       update_routing_table(session);
+
                        if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
                                ipconfig_ipv4_changed(session);
                        else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
-- 
1.8.5.3

_______________________________________________
connman mailing list
connman@connman.net
https://lists.connman.net/mailman/listinfo/connman

Reply via email to