Comment: Formatting errors fixed. Session notification as per priority is now
done only when service state changes to online.
---
 include/service.h |    2 +
 src/service.c     |    9 +++
 src/session.c     |  162 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 170 insertions(+), 3 deletions(-)

diff --git a/include/service.h b/include/service.h
index 36c8658..ea0f128 100644
--- a/include/service.h
+++ b/include/service.h
@@ -94,6 +94,8 @@ void connman_service_unref(struct connman_service *service);
 
 enum connman_service_type connman_service_get_type(struct connman_service 
*service);
 char *connman_service_get_interface(struct connman_service *service);
+void connman_service_packet_stats(struct connman_service *service,
+                                       unsigned int *packets_transmitted);
 
 const char *connman_service_get_domainname(struct connman_service *service);
 char **connman_service_get_nameservers(struct connman_service *service);
diff --git a/src/service.c b/src/service.c
index 1b95995..31e17be 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1153,6 +1153,15 @@ static void reset_stats(struct connman_service *service)
        g_timer_reset(service->stats_roaming.timer);
 }
 
+void connman_service_packet_stats(struct connman_service *service,
+                                 unsigned int *packets_transmitted)
+{
+       struct connman_stats_data *data;
+       data = &stats_get(service)->data;
+
+       *packets_transmitted = (data->rx_packets + data->tx_packets);
+}
+
 static struct connman_service *get_default(void)
 {
        struct connman_service *service;
diff --git a/src/session.c b/src/session.c
index 990caea..58096a9 100644
--- a/src/session.c
+++ b/src/session.c
@@ -30,8 +30,15 @@
 
 #include "connman.h"
 
+#define MIN_PACKET_THRESHOLD (1)       /*min packet count before notify*/
+
+#define STATS_UPDATE_INTERVAL (1)      /*Macro to change update stats*/
+
+#define MONITOR_INTERVAL (2)           /*Macro to check traffic*/
+
 static DBusConnection *connection;
 static GHashTable *session_hash;
+GSList *session_master_list = NULL;
 static connman_bool_t sessionmode;
 static struct session_info *ecall_info;
 
@@ -109,6 +116,12 @@ struct bearer_info {
        enum connman_service_type service_type;
 };
 
+struct service_session_info {
+       struct connman_service *service;
+       GSList *list;
+       unsigned int packets;
+};
+
 static const char *trigger2string(enum connman_session_trigger trigger)
 {
        switch (trigger) {
@@ -1321,6 +1334,8 @@ static int session_disconnect(struct connman_session 
*session)
        deselect_and_disconnect(session,
                                CONNMAN_SESSION_REASON_DISCONNECT);
 
+       session_master_list = g_slist_remove(session_master_list, session);
+
        g_hash_table_remove(session_hash, session->session_path);
 
        return 0;
@@ -1518,7 +1533,7 @@ int __connman_session_create(DBusMessage *msg)
        }
 
        g_hash_table_replace(session_hash, session->session_path, session);
-
+       session_master_list = g_slist_append(session_master_list, session);
        DBG("add %s", session->session_path);
 
        if (g_dbus_register_interface(connection, session->session_path,
@@ -1688,18 +1703,129 @@ static void service_remove(struct connman_service 
*service)
        }
 }
 
+static void insert_at_position(GSList **session_list, guint position,
+                              struct connman_session *new_session,
+                              gboolean *appended)
+{
+       struct connman_session *session = NULL;
+       struct session_info *info = NULL;
+       struct session_info *new_info = NULL;
+
+       if (session_list == NULL || new_session == NULL) {
+               DBG("session list or session NULL");
+               return;
+       }
+
+       if (*session_list == NULL)
+               return;
+
+       session = (struct connman_session *)g_slist_nth_data(*session_list,
+                                                               position);
+       info = session->info;
+
+       if (session == NULL)
+               return;
+
+       new_info = new_session->info;
+
+       if (info == NULL || new_info == NULL) {
+               DBG("info or new_info NULL");
+               return;
+       }
+
+       if (new_info->priority != info->priority) {
+               if (new_info->priority == TRUE) {
+                       *session_list = g_slist_insert(*session_list,
+                                                       new_session, position);
+                       *appended = TRUE;
+               }
+       } else {
+               if (g_slist_index(session_master_list, new_session) <
+                 g_slist_index(session_master_list, session)) {
+                       *session_list = g_slist_insert(*session_list,
+                                                       new_session, position);
+                       *appended = TRUE;
+               }
+       }
+}
+
+static void sort_session_list(GSList **session_list,
+                             struct connman_session *session)
+{
+       GSList **list = session_list;
+       guint pos = 0;
+       gboolean appended = FALSE;
+       for (pos = 0; pos < g_slist_length(*list); pos++) {
+               insert_at_position(list, pos, session, &appended);
+               if (appended == TRUE)
+                       break;
+       }
+       if (appended == FALSE)
+               *list = g_slist_append(*list, session);
+}
+
+static void session_called(gpointer data, gpointer user_data)
+{
+       struct connman_session *session = data;
+       session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
+}
+
+static gboolean monitor_traffic_and_notify(gpointer user_data)
+{
+       struct service_session_info *service_session_info =
+                               (struct service_session_info *)user_data;
+       struct connman_service *service = service_session_info->service;
+       GSList *list = service_session_info->list;
+       unsigned int packets_old = service_session_info->packets, packets = 0;
+       connman_service_packet_stats(service, &packets);
+       service_session_info->packets = packets;
+       packets_old = packets - packets_old;
+
+       if (packets_old <= MIN_PACKET_THRESHOLD) {
+               __connman_rtnl_update_interval_remove(STATS_UPDATE_INTERVAL);
+               g_slist_foreach(list, (GFunc) session_called, NULL);
+               g_slist_free(list);
+               list = NULL;
+               g_free(service_session_info);
+               service_session_info = NULL;
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+static void monitor_interface_usage(gpointer user_data)
+{
+       struct service_session_info *service_session_info =
+                                   (struct service_session_info *)user_data;
+       __connman_rtnl_update_interval_add(STATS_UPDATE_INTERVAL);
+       connman_service_packet_stats(service_session_info->service,
+                                       &service_session_info->packets);
+       g_timeout_add_seconds(MONITOR_INTERVAL, monitor_traffic_and_notify,
+                               service_session_info);
+}
+
 static void service_state_changed(struct connman_service *service,
                                        enum connman_service_state state)
 {
        GHashTableIter iter;
        gpointer key, value;
+       struct service_session_info *service_session_info;
+       GSList *priority_session_list = NULL;
+       GSList *non_priority_session_list = NULL;
 
        DBG("service %p state %d", service, state);
 
+       service_session_info = g_try_new0(struct service_session_info, 1);
+       if (service_session_info == NULL) {
+               DBG("Service Session List memory allocation failed");
+               return;
+       }
+
        g_hash_table_iter_init(&iter, session_hash);
 
        while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
                struct connman_session *session = value;
+               struct session_info *info = session->info;
                GSequenceIter *service_iter;
 
                service_iter = g_hash_table_lookup(session->service_hash, 
service);
@@ -1709,9 +1835,39 @@ static void service_state_changed(struct connman_service 
*service,
                        entry = g_sequence_get(service_iter);
                        entry->state = state;
                }
+               if (state == CONNMAN_SERVICE_STATE_ONLINE) {
+                       if (info->priority == TRUE) {
+                               sort_session_list(&priority_session_list,
+                                                       session);
+                       } else {
+                               sort_session_list(&non_priority_session_list,
+                                                       session);
+                       }
+               } else {
+                       session_changed(session,
+                                       CONNMAN_SESSION_TRIGGER_SERVICE);
+               }
+       }
+
+       if ((priority_session_list != NULL) ||
+               (non_priority_session_list != NULL)) {
+               g_slist_foreach(priority_session_list,
+                               (GFunc) session_called, NULL);
 
-               session_changed(session,
-                               CONNMAN_SESSION_TRIGGER_SERVICE);
+               if ((priority_session_list != NULL) &&
+                       (non_priority_session_list != NULL)) {
+                       service_session_info->service = service;
+                       service_session_info->list = non_priority_session_list;
+
+                       monitor_interface_usage(service_session_info);
+               } else {
+                       g_slist_foreach(non_priority_session_list,
+                                       (GFunc) session_called, NULL);
+                       g_slist_free(non_priority_session_list);
+                       non_priority_session_list = NULL;
+               }
+               g_slist_free(priority_session_list);
+               priority_session_list = NULL;
        }
 }
 
-- 
1.7.6
Thanks and Regards,
Sree Gowri.
=====-----=====-----=====
Notice: The information contained in this e-mail
message and/or attachments to it may contain 
confidential or privileged information. If you are 
not the intended recipient, any dissemination, use, 
review, distribution, printing or copying of the 
information contained in this e-mail message 
and/or attachments to it are strictly prohibited. If 
you have received this communication in error, 
please notify us by reply e-mail or telephone and 
immediately and permanently delete the message 
and any attachments. Thank you



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

Reply via email to