From c9f804e1cce4290834b39e937e2a228960e88869 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 20 Sep 2010 10:02:47 +0900 Subject: [PATCH] Add support for PAC runner configuration updates --- plugins/pacrunner.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) diff --git a/plugins/pacrunner.c b/plugins/pacrunner.c index 06a309d..82fd8fb 100644 --- a/plugins/pacrunner.c +++ b/plugins/pacrunner.c @@ -23,16 +23,227 @@ #include #endif +#include + +#include + #define CONNMAN_API_SUBJECT_TO_CHANGE #include +#include +#include +#include + +#define PACRUNNER_SERVICE "org.pacrunner" +#define PACRUNNER_INTERFACE "org.pacrunner.Manager" +#define PACRUNNER_PATH "/org/pacrunner/manager" + +#define DBUS_TIMEOUT 5000 + +static DBusConnection *connection; + +static struct connman_service *default_service = NULL; +static char *current_config = NULL; + +static void create_config_reply(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply = dbus_pending_call_steal_reply(call); + const char *path; + + DBG(""); + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + connman_error("Failed to create proxy configuration"); + goto done; + } + + if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID) == FALSE) + goto done; + + g_free(current_config); + current_config = g_strdup(path); + +done: + dbus_message_unref(reply); +} + +static void add_dict_with_string_value(DBusMessageIter *iter, + const char *key, const char *str) +{ + DBusMessageIter dict, entry, value; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_STRING_AS_STRING, &value); + dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str); + dbus_message_iter_close_container(&entry, &value); + + dbus_message_iter_close_container(&dict, &entry); + dbus_message_iter_close_container(iter, &dict); +} + +static void create_proxy_configuration(const char *url) +{ + DBusMessage *msg; + DBusMessageIter iter; + DBusPendingCall *call; + dbus_bool_t result; + + if (url == NULL) + return; + + DBG("url %s", url); + + msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH, + PACRUNNER_INTERFACE, "CreateProxyConfiguration"); + if (msg == NULL) + return; + + dbus_message_set_auto_start(msg, FALSE); + + dbus_message_iter_init_append(msg, &iter); + add_dict_with_string_value(&iter, "URL", url); + + result = dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT); + + dbus_message_unref(msg); + + if (result == FALSE || call == NULL) + return; + + dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL); + + dbus_pending_call_unref(call); +} + +static void destroy_config_reply(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply = dbus_pending_call_steal_reply(call); + + DBG(""); + + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) + connman_error("Failed to destoy proxy configuration"); + + dbus_message_unref(reply); +} + +static void destroy_proxy_configuration(void) +{ + DBusMessage *msg; + DBusPendingCall *call; + dbus_bool_t result; + + if (current_config == NULL) + return; + + DBG(""); + + msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH, + PACRUNNER_INTERFACE, "DestroyProxyConfiguration"); + if (msg == NULL) + return; + + dbus_message_set_auto_start(msg, FALSE); + + dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, ¤t_config, + DBUS_TYPE_INVALID); + + result = dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT); + + dbus_message_unref(msg); + + if (result == FALSE || call == NULL) + return; + + dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL); + + dbus_pending_call_unref(call); + + g_free(current_config); + current_config = NULL; +} + +static void default_service_changed(struct connman_service *service) +{ + const char *url; + + DBG("service %p", service); + + if (service == default_service) + return; + + default_service = service; + + destroy_proxy_configuration(); + + url = connman_service_get_proxy_autoconfig(service); + create_proxy_configuration(url); +} + +static struct connman_notifier pacrunner_notifier = { + .name = "pacrunner", + .default_changed = default_service_changed, +}; + +static void pacrunner_connect(DBusConnection *conn, void *user_data) +{ + const char *url; + + DBG(""); + + url = connman_service_get_proxy_autoconfig(default_service); + create_proxy_configuration(url); +} + +static void pacrunner_disconnect(DBusConnection *conn, void *user_data) +{ + DBG(""); + + g_free(current_config); + current_config = NULL; +} + +static guint pacrunner_watch; static int pacrunner_init(void) { + connection = connman_dbus_get_connection(); + if (connection == NULL) + return -EIO; + + pacrunner_watch = g_dbus_add_service_watch(connection, + PACRUNNER_SERVICE, pacrunner_connect, + pacrunner_disconnect, NULL, NULL); + if (pacrunner_watch == 0) { + dbus_connection_unref(connection); + return -EIO; + } + + connman_notifier_register(&pacrunner_notifier); + return 0; } static void pacrunner_exit(void) { + connman_notifier_unregister(&pacrunner_notifier); + + g_dbus_remove_watch(connection, pacrunner_watch); + + destroy_proxy_configuration(); + + dbus_connection_unref(connection); } CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION, -- 2.7.4