Comment: Implementation of delay before notifying non priority sessions
---
 include/service.h |    1 +
 src/service.c     |    9 ++
 src/session.c     |  228 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 231 insertions(+), 7 deletions(-)

diff --git a/include/service.h b/include/service.h
index 36c8658..d041ead 100644
--- a/include/service.h
+++ b/include/service.h
@@ -94,6 +94,7 @@ 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..31aed24 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) {
@@ -1117,16 +1130,79 @@ static DBusMessage *disconnect_session(DBusConnection 
*conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
+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 and 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 and 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 session_called(gpointer data, gpointer user_data)
+{
+       struct connman_session *session = data;
+       gboolean *ecall = user_data;
+       if (ecall)
+               session_changed(session, CONNMAN_SESSION_TRIGGER_ECALL);
+       else
+               session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
+}
+
 static void update_ecall_sessions(struct connman_session *session)
 {
        struct session_info *info = session->info;
        struct connman_session *session_iter;
        GHashTableIter iter;
        gpointer key, value;
+       GSList *session_list = NULL;
+       gboolean ecall = TRUE;
 
        g_hash_table_iter_init(&iter, session_hash);
 
        while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               gboolean appended = FALSE;
+               guint pos = 0;
                session_iter = value;
 
                if (session_iter == session)
@@ -1135,8 +1211,21 @@ static void update_ecall_sessions(struct connman_session 
*session)
                session_iter->info->ecall = info->ecall;
                session_iter->info_dirty = TRUE;
 
-               session_changed(session_iter, CONNMAN_SESSION_TRIGGER_ECALL);
+               for (pos = 0; pos < g_slist_length(session_list); pos++) {
+                       insert_at_position(&session_list,
+                                          pos, session, &appended);
+                       if (appended == TRUE) {
+                               break;
+                       }
+                 }
+                 if (appended == FALSE) {
+                       session_list = g_slist_append(session_list, session);
+                 }
        }
+       g_slist_foreach(session_list, (GFunc)session_called, (gpointer *)ecall);
+
+       g_slist_free(session_list);
+       session_list = NULL;
 }
 
 static void update_ecall(struct connman_session *session)
@@ -1321,6 +1410,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 +1609,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,
@@ -1631,12 +1722,15 @@ static void service_add(struct connman_service *service,
        gpointer key, value;
        struct connman_session *session;
        struct service_entry *entry;
+       GSList *session_list = NULL;
 
        DBG("service %p", service);
 
        g_hash_table_iter_init(&iter, session_hash);
 
        while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               gboolean appended = FALSE;
+               guint pos = 0;
                session = value;
 
                if (service_match(session, service) == FALSE)
@@ -1654,9 +1748,22 @@ static void service_add(struct connman_service *service,
 
                g_hash_table_replace(session->service_hash, service,
                                        iter_service_list);
-
-               session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
+               for (pos = 0; pos < g_slist_length(session_list); pos++) {
+                       insert_at_position(&session_list,
+                                          pos, session, &appended);
+                       if (appended == TRUE) {
+                               break;
+                       }
+               }
+               if (appended == FALSE) {
+                       session_list = g_slist_append(session_list, session);
+               }
        }
+
+       g_slist_foreach(session_list, (GFunc) session_called, NULL);
+
+       g_slist_free(session_list);
+       session_list = NULL;
 }
 
 static void service_remove(struct connman_service *service)
@@ -1666,6 +1773,7 @@ static void service_remove(struct connman_service 
*service)
        gpointer key, value;
        struct connman_session *session;
        struct session_info *info;
+       GSList *session_list = NULL;
 
        DBG("service %p", service);
 
@@ -1675,6 +1783,8 @@ static void service_remove(struct connman_service 
*service)
                GSequenceIter *iter;
                session = value;
                info = session->info;
+               gboolean appended = FALSE;
+               guint pos = 0;
 
                iter = g_hash_table_lookup(session->service_hash, service);
                if (iter == NULL)
@@ -1684,8 +1794,57 @@ static void service_remove(struct connman_service 
*service)
 
                if (info->entry != NULL && info->entry->service == service)
                        info->entry = NULL;
-               session_changed(session, CONNMAN_SESSION_TRIGGER_SERVICE);
+
+               for (pos = 0; pos < g_slist_length(session_list); pos++) {
+                       insert_at_position(&session_list,
+                                          pos, session, &appended);
+                       if (appended == TRUE) {
+                               break;
+                       }
+               }
+               if (appended == FALSE) {
+                       session_list = g_slist_append(session_list, session);
+               }
+       }
+
+       g_slist_foreach(session_list, (GFunc) session_called, NULL);
+
+       g_slist_free(session_list);
+       session_list = NULL;
+}
+
+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,
@@ -1693,14 +1852,25 @@ static void service_state_changed(struct 
connman_service *service,
 {
        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 (NULL == service_session_info) {
+               DBG("Service Session List memory allocation failed");
+       }
+
        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;
+               gboolean appended = FALSE;
+               guint pos = 0;
 
                service_iter = g_hash_table_lookup(session->service_hash, 
service);
                if (service_iter != NULL) {
@@ -1709,10 +1879,54 @@ static void service_state_changed(struct 
connman_service *service,
                        entry = g_sequence_get(service_iter);
                        entry->state = state;
                }
+                if (info->priority == TRUE) {
+                       for (pos = 0;
+                            pos < g_slist_length(priority_session_list);
+                            pos++) {
+                               insert_at_position(&priority_session_list,
+                                                  pos, session, &appended);
+                               if (TRUE == appended) {
+                                       break;
+                               }
+                       }
+                       if (FALSE == appended) {
+                               priority_session_list =
+                               g_slist_append(priority_session_list, session);
+                       }
+               } else {
+                       for (pos = 0; pos < g_slist_length(
+                         non_priority_session_list); pos++) {
+                               insert_at_position(&non_priority_session_list,
+                                                  pos, session, &appended);
+                               if (TRUE == appended) {
+                                       break;
+                               }
+                       }
+                       if (FALSE == appended) {
+                               non_priority_session_list =
+                               g_slist_append(non_priority_session_list,
+                                              session);
+                       }
+               }
+       }
+
+       g_slist_foreach(priority_session_list, (GFunc) session_called, NULL);
 
-               session_changed(session,
-                               CONNMAN_SESSION_TRIGGER_SERVICE);
+       if ((state == CONNMAN_SERVICE_STATE_ONLINE) &&
+           (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;
 }
 
 static void ipconfig_changed(struct connman_service *service,
-- 
1.7.6
=====-----=====-----=====
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