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