Add framework for counter callbacks
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 5 Jan 2010 06:42:45 +0000 (22:42 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 5 Jan 2010 06:42:45 +0000 (22:42 -0800)
Makefile.am
doc/manager-api.txt
include/dbus.h
src/connman-dbus.conf
src/connman.h
src/counter.c [new file with mode: 0644]
src/main.c
src/manager.c
test/test-counter [new file with mode: 0755]

index 2b1b87d..99f1fb1 100644 (file)
@@ -52,7 +52,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(builtin_sources) \
                        src/ipv4.c src/dhcp.c src/rtnl.c src/inet.c \
                        src/utsname.c src/timeserver.c src/rfkill.c \
                        src/wifi.c src/storage.c src/dbus.c src/config.c \
-                       src/technology.c
+                       src/technology.c src/counter.c
 
 if UDEV
 src_connmand_SOURCES += src/udev.c
@@ -137,7 +137,7 @@ test_scripts = test/get-state test/list-profiles test/list-services \
                test/simple-agent test/show-introspection test/test-compat \
                test/test-manager test/test-connman test/monitor-connman \
                test/connect-vpn test/disconnect-vpn test/list-providers \
-               test/monitor-manager
+               test/monitor-manager test/test-counter
 
 if TEST
 testdir = $(pkglibdir)/test
index a50b4ef..35477dc 100644 (file)
@@ -105,6 +105,18 @@ Methods            dict GetProperties()
 
                        Possible Errors: [service].Error.InvalidArguments
 
+               void RegisterCounter(object path, uint32 interval)
+
+                       Register a new counter for user notifications.
+
+                       Possible Errors: [service].Error.InvalidArguments
+
+               void UnregisterCounter(object path)
+
+                       Unregister an existing counter.
+
+                       Possible Errors: [service].Error.InvalidArguments
+
 Signals                PropertyChanged(string name, variant value)
 
                        This signal indicates a changed value of the given
index 73bda69..36629df 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #define CONNMAN_DEBUG_INTERFACE                CONNMAN_SERVICE ".Debug"
 #define CONNMAN_ERROR_INTERFACE                CONNMAN_SERVICE ".Error"
 #define CONNMAN_AGENT_INTERFACE                CONNMAN_SERVICE ".Agent"
+#define CONNMAN_COUNTER_INTERFACE      CONNMAN_SERVICE ".Counter"
 
 #define CONNMAN_MANAGER_INTERFACE      CONNMAN_SERVICE ".Manager"
 #define CONNMAN_MANAGER_PATH           "/"
index 2be3764..345b87e 100644 (file)
@@ -5,6 +5,7 @@
         <allow own="org.moblin.connman"/>
         <allow send_destination="org.moblin.connman"/>
         <allow send_interface="org.moblin.connman.Agent"/>
+        <allow send_interface="org.moblin.connman.Counter"/>
     </policy>
     <policy user="system">
         <allow send_destination="org.moblin.connman"/>
index 61dd411..6f6b621 100644 (file)
@@ -65,6 +65,13 @@ void __connman_agent_cleanup(void);
 int __connman_agent_register(const char *sender, const char *path);
 int __connman_agent_unregister(const char *sender, const char *path);
 
+int __connman_counter_register(const char *owner, const char *path,
+                                               unsigned int interval);
+int __connman_counter_unregister(const char *owner, const char *path);
+
+int __connman_counter_init(void);
+void __connman_counter_cleanup(void);
+
 struct connman_service;
 
 typedef void (* passphrase_cb_t) (struct connman_service *service,
diff --git a/src/counter.c b/src/counter.c
new file mode 100644 (file)
index 0000000..9dea4b7
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gdbus.h>
+
+#include "connman.h"
+
+static DBusConnection *connection;
+
+static GHashTable *counter_table;
+static GHashTable *owner_mapping;
+
+struct connman_counter {
+       char *owner;
+       char *path;
+       guint timeout;
+       guint watch;
+};
+
+static void remove_counter(gpointer user_data)
+{
+       struct connman_counter *counter = user_data;
+
+       DBG("owner %s path %s", counter->owner, counter->path);
+
+       if (counter->watch > 0)
+               g_dbus_remove_watch(connection, counter->watch);
+
+       if (counter->timeout > 0)
+               g_source_remove(counter->timeout);
+
+       g_free(counter->owner);
+       g_free(counter->path);
+       g_free(counter);
+}
+
+static void owner_disconnect(DBusConnection *connection, void *user_data)
+{
+       struct connman_counter *counter = user_data;
+
+       DBG("owner %s path %s", counter->owner, counter->path);
+
+       g_hash_table_remove(owner_mapping, counter->owner);
+       g_hash_table_remove(counter_table, counter->path);
+}
+
+static gboolean counter_timeout(gpointer user_data)
+{
+       struct connman_counter *counter = user_data;
+       DBusMessage *message;
+
+       DBG("owner %s path %s", counter->owner, counter->path);
+
+       message = dbus_message_new_method_call(counter->owner, counter->path,
+                                       CONNMAN_COUNTER_INTERFACE, "Usage");
+       if (message == NULL)
+               return TRUE;
+
+       dbus_message_set_no_reply(message, TRUE);
+
+       g_dbus_send_message(connection, message);
+
+       return TRUE;
+}
+
+int __connman_counter_register(const char *owner, const char *path,
+                                               unsigned int interval)
+{
+       struct connman_counter *counter;
+
+       DBG("owner %s path %s interval %u", owner, path, interval);
+
+       counter = g_hash_table_lookup(counter_table, path);
+       if (counter != NULL)
+               return -EEXIST;
+
+       counter = g_try_new0(struct connman_counter, 1);
+       if (counter == NULL)
+               return -ENOMEM;
+
+       counter->owner = g_strdup(owner);
+       counter->path = g_strdup(path);
+
+       g_hash_table_replace(counter_table, counter->path, counter);
+       g_hash_table_replace(owner_mapping, counter->owner, counter);
+
+       counter->timeout = g_timeout_add_seconds(interval,
+                                               counter_timeout, counter);
+
+       counter->watch = g_dbus_add_disconnect_watch(connection, owner,
+                                       owner_disconnect, counter, NULL);
+
+       return 0;
+}
+
+int __connman_counter_unregister(const char *owner, const char *path)
+{
+       struct connman_counter *counter;
+
+       DBG("owner %s path %s", owner, path);
+
+       counter = g_hash_table_lookup(counter_table, path);
+       if (counter == NULL)
+               return -ESRCH;
+
+       if (g_strcmp0(owner, counter->owner) != 0)
+               return -EACCES;
+
+       g_hash_table_remove(owner_mapping, counter->owner);
+       g_hash_table_remove(counter_table, counter->path);
+
+       return 0;
+}
+
+static void release_counter(gpointer key, gpointer value, gpointer user_data)
+{
+       struct connman_counter *counter = value;
+       DBusMessage *message;
+
+       DBG("owner %s path %s", counter->owner, counter->path);
+
+       message = dbus_message_new_method_call(counter->owner, counter->path,
+                                       CONNMAN_COUNTER_INTERFACE, "Release");
+       if (message == NULL)
+               return;
+
+       dbus_message_set_no_reply(message, TRUE);
+
+       g_dbus_send_message(connection, message);
+}
+
+int __connman_counter_init(void)
+{
+       DBG("");
+
+       connection = connman_dbus_get_connection();
+       if (connection == NULL)
+               return -1;
+
+       counter_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                       NULL, remove_counter);
+       owner_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                               NULL, NULL);
+
+       return 0;
+}
+
+void __connman_counter_cleanup(void)
+{
+       DBG("");
+
+       if (connection == NULL)
+               return;
+
+       g_hash_table_foreach(counter_table, release_counter, NULL);
+
+       g_hash_table_destroy(owner_mapping);
+       g_hash_table_destroy(counter_table);
+
+       dbus_connection_unref(connection);
+}
index c8b4389..aef6d1b 100644 (file)
@@ -207,6 +207,7 @@ int main(int argc, char *argv[])
        __connman_element_init(option_device, option_nodevice);
 
        __connman_agent_init();
+       __connman_counter_init();
        __connman_manager_init(option_compat);
        __connman_profile_init();
        __connman_config_init();
@@ -246,6 +247,7 @@ int main(int argc, char *argv[])
        __connman_config_cleanup();
        __connman_profile_cleanup();
        __connman_manager_cleanup();
+       __connman_counter_cleanup();
        __connman_agent_cleanup();
 
        __connman_element_cleanup();
index b10dd3d..cc5d163 100644 (file)
@@ -504,6 +504,48 @@ static DBusMessage *unregister_agent(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
+static DBusMessage *register_counter(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       const char *sender, *path;
+       unsigned int interval;
+       int err;
+
+       DBG("conn %p", conn);
+
+       sender = dbus_message_get_sender(msg);
+
+       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+                                               DBUS_TYPE_UINT32, &interval,
+                                                       DBUS_TYPE_INVALID);
+
+       err = __connman_counter_register(sender, path, interval);
+       if (err < 0)
+               return __connman_error_failed(msg, -err);
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *unregister_counter(DBusConnection *conn,
+                                       DBusMessage *msg, void *data)
+{
+       const char *sender, *path;
+       int err;
+
+       DBG("conn %p", conn);
+
+       sender = dbus_message_get_sender(msg);
+
+       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+                                                       DBUS_TYPE_INVALID);
+
+       err = __connman_counter_unregister(sender, path);
+       if (err < 0)
+               return __connman_error_failed(msg, -err);
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
 static GDBusMethodTable manager_methods[] = {
        { "GetProperties",     "",      "a{sv}", get_properties     },
        { "SetProperty",       "sv",    "",      set_property       },
@@ -522,6 +564,8 @@ static GDBusMethodTable manager_methods[] = {
                                                G_DBUS_METHOD_FLAG_ASYNC },
        { "RegisterAgent",     "o",     "",      register_agent     },
        { "UnregisterAgent",   "o",     "",      unregister_agent   },
+       { "RegisterCounter",   "ou",    "",      register_counter   },
+       { "UnregisterCounter", "o",     "",      unregister_counter },
        { },
 };
 
diff --git a/test/test-counter b/test/test-counter
new file mode 100755 (executable)
index 0000000..b0173a4
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+import gobject
+
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+class Counter(dbus.service.Object):
+       @dbus.service.method("org.moblin.connman.Counter",
+                                       in_signature='', out_signature='')
+       def Release(self):
+               print("Release")
+               mainloop.quit()
+
+       @dbus.service.method("org.moblin.connman.Counter",
+                                       in_signature='', out_signature='')
+       def Usage(self):
+               print("Usage")
+
+if __name__ == '__main__':
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       bus = dbus.SystemBus()
+       manager = dbus.Interface(bus.get_object('org.moblin.connman', "/"),
+                                       'org.moblin.connman.Manager')
+
+       path = "/test/counter"
+       object = Counter(bus, path)
+
+       manager.RegisterCounter(path, dbus.UInt32(2))
+
+       mainloop = gobject.MainLoop()
+       mainloop.run()
+
+       #manager.UnregisterCounter(path)