From: Daniel Wagner <[email protected]>

Instead using the glib sort insert function we open code the
sorting directly. The reason for this is that we'd like to use
a pick sort instead of in list sorting.

For this we iterate over the bearer list and remove the matching
services from the session->service_list and append it to a tempory
list. With this we sort according the bearer ordering.
---
 src/session.c | 146 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 66 insertions(+), 80 deletions(-)

diff --git a/src/session.c b/src/session.c
index bcbb009..03a3911 100644
--- a/src/session.c
+++ b/src/session.c
@@ -971,7 +971,7 @@ static void ipconfig_ipv6_changed(struct connman_session 
*session)
                                                info->entry->service);
 }
 
-static connman_bool_t service_type_match(struct connman_session *session,
+static connman_bool_t service_match(struct connman_session *session,
                                        struct connman_service *service)
 {
        struct session_info *info = session->info;
@@ -997,104 +997,90 @@ static connman_bool_t service_type_match(struct 
connman_session *session,
        return FALSE;
 }
 
-static connman_bool_t service_match(struct connman_session *session,
-                                       struct connman_service *service)
+static GList *find_and_remove_by_name(GList *list, const char *name,
+                               GList **service_list)
 {
-       if (service_type_match(session, service) == FALSE)
-               return FALSE;
+       GList *it;
 
-       return TRUE;
+       for (it = list; it != NULL; it = it->next) {
+               struct service_entry *e = it->data;
+               const char *ident = __connman_service_get_ident(e->service);
+
+               if (g_strcmp0(name, ident) == 0) {
+                       *service_list = g_list_append(*service_list, e);
+                       return g_list_remove_link(list, it);
+               }
+       }
+
+       return list;
 }
 
-static int service_type_weight(enum connman_service_type type)
+static GList *find_and_remove_by_type(GList *list,
+                               enum connman_service_type type,
+                               GList** service_list)
 {
-       /*
-        * 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
-        */
+       GList *it, *next;
 
-       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;
+       for (it = list; it != NULL;) {
+               struct service_entry *e = it->data;
+               enum connman_service_type t = 
connman_service_get_type(e->service);
+
+               next = it->next;
+
+               if (t == type) {
+                       list = g_list_remove_link(list, it);
+                       *service_list = g_list_append(*service_list, e);
+               }
+
+               it = next;
        }
 
-       return 0;
+       return list;
 }
 
-static gint sort_allowed_bearers(struct connman_service *service_a,
-                                       struct connman_service *service_b,
-                                       struct connman_session *session)
+static void sort_services(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);
+       GList *service_list = NULL;
 
        for (list = info->config.allowed_bearers;
                        list != NULL; list = list->next) {
                char *bearer_name = list->data;
                enum connman_service_type bearer;
 
-               if (bearer2service(bearer_name, &bearer) < 0)
-                       return -1;
-
-               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 (bearer2service(bearer_name, &bearer) < 0) {
+                       session->service_list = find_and_remove_by_name(
+                                       session->service_list, bearer_name,
+                                       &service_list);
+                       continue;
                }
 
-               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;
+               if (bearer == CONNMAN_SERVICE_TYPE_UNKNOWN) {
+                       session->service_list = find_and_remove_by_type(
+                               session->service_list,
+                               CONNMAN_SERVICE_TYPE_ETHERNET, &service_list);
+
+                       session->service_list = find_and_remove_by_type(
+                               session->service_list,
+                               CONNMAN_SERVICE_TYPE_BLUETOOTH, &service_list);
+
+                       session->service_list = find_and_remove_by_type(
+                               session->service_list,
+                               CONNMAN_SERVICE_TYPE_WIFI, &service_list);
+
+                       session->service_list = find_and_remove_by_type(
+                               session->service_list,
+                               CONNMAN_SERVICE_TYPE_CELLULAR, &service_list);
+               } else
+                       session->service_list = find_and_remove_by_type(
+                               session->service_list, bearer, &service_list);
+
+               if (session->service_list == NULL)
+                       break;
        }
 
-       return 0;
-}
-
-static gint sort_services(gconstpointer a, gconstpointer b, gpointer user_data)
-{
-       struct service_entry *entry_a = (void *)a;
-       struct service_entry *entry_b = (void *)b;
-       struct connman_session *session = user_data;
-
-       return sort_allowed_bearers(entry_a->service, entry_b->service,
-                               session);
+       session->service_list = service_list;
 }
 
 static enum connman_session_state service_to_session_state(enum 
connman_service_state state)
@@ -1483,8 +1469,7 @@ static void populate_service_list(struct connman_session 
*session)
                                                        entry);
        }
 
-       session->service_list = g_list_sort_with_data(session->service_list,
-                                               sort_services, session);
+       sort_services(session);
 }
 
 static void session_changed(struct connman_session *session,
@@ -2243,8 +2228,9 @@ static void service_add(struct connman_service *service,
                if (entry == NULL)
                        continue;
 
-               session->service_list = g_list_insert_sorted_with_data(
-                       session->service_list, entry, sort_services, session);
+               session->service_list = g_list_prepend(session->service_list,
+                                                       entry);
+               sort_services(session);
 
                g_hash_table_replace(session->service_hash, service, entry);
 
-- 
1.8.2.rc3.16.gce432ca

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

Reply via email to