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