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