summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-04-07 16:54:19 -0700
committerMarcel Holtmann <marcel@holtmann.org>2009-04-07 21:02:48 -0700
commitc6dc4196705b7b93e11b6687b10cc49a7f038c34 (patch)
tree448353cc31e89aeebb96c570517cc175c406e4a2
parent5a5a93105bd1e2e70044b4d466a7a37ec696c94d (diff)
downloadconnman-c6dc4196705b7b93e11b6687b10cc49a7f038c34.tar.gz
connman-c6dc4196705b7b93e11b6687b10cc49a7f038c34.tar.bz2
connman-c6dc4196705b7b93e11b6687b10cc49a7f038c34.zip
Add service initialization and lifetime tracking support
-rw-r--r--include/service.h3
-rw-r--r--src/connman.h3
-rw-r--r--src/element.c2
-rw-r--r--src/service.c108
4 files changed, 116 insertions, 0 deletions
diff --git a/include/service.h b/include/service.h
index 9e97cf63..e83911c9 100644
--- a/include/service.h
+++ b/include/service.h
@@ -65,6 +65,9 @@ enum connman_service_state {
struct connman_service;
+extern struct connman_service *connman_service_get(const char *identifier);
+extern void connman_service_put(struct connman_service *service);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/connman.h b/src/connman.h
index 44cba117..a97dfadd 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -209,6 +209,9 @@ int __connman_profile_remove_network(struct connman_network *network);
#include <connman/service.h>
+int __connman_service_init(void);
+void __connman_service_cleanup(void);
+
#include <connman/notifier.h>
int __connman_notifier_init(void);
diff --git a/src/element.c b/src/element.c
index b68e954e..7b24a98e 100644
--- a/src/element.c
+++ b/src/element.c
@@ -1284,6 +1284,7 @@ int __connman_element_init(DBusConnection *conn, const char *device,
element_root = g_node_new(element);
__connman_notifier_init();
+ __connman_service_init();
__connman_network_init();
__connman_device_init();
@@ -1368,6 +1369,7 @@ void __connman_element_cleanup(void)
__connman_device_cleanup();
__connman_network_cleanup();
+ __connman_service_cleanup();
__connman_notifier_cleanup();
g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
diff --git a/src/service.c b/src/service.c
index f272fe37..9c95fc6e 100644
--- a/src/service.c
+++ b/src/service.c
@@ -25,7 +25,14 @@
#include "connman.h"
+static DBusConnection *connection = NULL;
+
+static GSequence *service_list = NULL;
+static GHashTable *service_hash = NULL;
+
struct connman_service {
+ gint refcount;
+ char *identifier;
char *path;
enum connman_service_type type;
enum connman_service_mode mode;
@@ -35,3 +42,104 @@ struct connman_service {
connman_bool_t favorite;
char *name;
};
+
+static void service_free(gpointer data)
+{
+ struct connman_service *service = data;
+
+ DBG("service %p", service);
+
+ g_hash_table_remove(service_hash, service->identifier);
+
+ g_free(service->name);
+ g_free(service->path);
+ g_free(service->identifier);
+ g_free(service);
+}
+
+static gint service_compare(gconstpointer a, gconstpointer b,
+ gpointer user_data)
+{
+ struct connman_service *service_a = (void *) a;
+ struct connman_service *service_b = (void *) b;
+
+ if (service_a->favorite == TRUE && service_b->favorite == FALSE)
+ return -1;
+
+ if (service_a->favorite == FALSE && service_b->favorite == TRUE)
+ return 1;
+
+ return (gint) service_b->strength - (gint) service_a->strength;
+}
+
+struct connman_service *connman_service_get(const char *identifier)
+{
+ struct connman_service *service;
+ GSequenceIter *iter;
+
+ iter = g_hash_table_lookup(service_hash, identifier);
+ if (iter != NULL) {
+ service = g_sequence_get(iter);
+ if (service != NULL)
+ g_atomic_int_inc(&service->refcount);
+ return service;
+ }
+
+ service = g_try_new0(struct connman_service, 1);
+ if (service == NULL)
+ return NULL;
+
+ DBG("service %p", service);
+
+ service->refcount = 1;
+ service->identifier = g_strdup(identifier);
+
+ iter = g_sequence_insert_sorted(service_list, service,
+ service_compare, NULL);
+
+ g_hash_table_insert(service_hash, service->identifier, iter);
+
+ return service;
+}
+
+void connman_service_put(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) {
+ GSequenceIter *iter;
+
+ iter = g_hash_table_lookup(service_hash, service->identifier);
+ if (iter != NULL)
+ g_sequence_remove(iter);
+ else
+ service_free(service);
+ }
+}
+
+int __connman_service_init(void)
+{
+ DBG("");
+
+ connection = connman_dbus_get_connection();
+
+ service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, NULL);
+
+ service_list = g_sequence_new(service_free);
+
+ return 0;
+}
+
+void __connman_service_cleanup(void)
+{
+ DBG("");
+
+ g_sequence_free(service_list);
+ service_list = NULL;
+
+ g_hash_table_destroy(service_hash);
+ service_hash = NULL;
+
+ dbus_connection_unref(connection);
+}