5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #define CONNMAN_API_SUBJECT_TO_CHANGE
31 #include <connman/plugin.h>
32 #include <connman/notifier.h>
33 #include <connman/dbus.h>
34 #include <connman/log.h>
36 #define PACRUNNER_SERVICE "org.pacrunner"
37 #define PACRUNNER_INTERFACE "org.pacrunner.Manager"
38 #define PACRUNNER_PATH "/org/pacrunner/manager"
40 #define DBUS_TIMEOUT 5000
42 static DBusConnection *connection;
44 static struct connman_service *default_service = NULL;
45 static char *current_config = NULL;
47 static void create_config_reply(DBusPendingCall *call, void *user_data)
49 DBusMessage *reply = dbus_pending_call_steal_reply(call);
54 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
55 connman_error("Failed to create proxy configuration");
59 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
60 DBUS_TYPE_INVALID) == FALSE)
63 g_free(current_config);
64 current_config = g_strdup(path);
67 dbus_message_unref(reply);
70 static void add_string_entry(DBusMessageIter *iter,
71 const char *key, const char *str)
73 DBusMessageIter value;
75 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
77 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
78 DBUS_TYPE_STRING_AS_STRING, &value);
79 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
80 dbus_message_iter_close_container(iter, &value);
83 static void create_proxy_configuration(const char *interface, const char *url)
86 DBusMessageIter iter, dict, entry;
87 DBusPendingCall *call;
93 DBG("interface %s url %s", interface, url);
95 msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
96 PACRUNNER_INTERFACE, "CreateProxyConfiguration");
100 dbus_message_set_auto_start(msg, FALSE);
102 dbus_message_iter_init_append(msg, &iter);
104 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
105 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
106 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
107 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
108 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
111 if (interface != NULL)
112 add_string_entry(&entry, "Interface", interface);
114 add_string_entry(&entry, "URL", url);
116 dbus_message_iter_close_container(&dict, &entry);
117 dbus_message_iter_close_container(&iter, &dict);
119 result = dbus_connection_send_with_reply(connection, msg,
120 &call, DBUS_TIMEOUT);
122 dbus_message_unref(msg);
124 if (result == FALSE || call == NULL)
127 dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);
129 dbus_pending_call_unref(call);
132 static void destroy_config_reply(DBusPendingCall *call, void *user_data)
134 DBusMessage *reply = dbus_pending_call_steal_reply(call);
138 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
139 connman_error("Failed to destoy proxy configuration");
141 dbus_message_unref(reply);
144 static void destroy_proxy_configuration(void)
147 DBusPendingCall *call;
150 if (current_config == NULL)
155 msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
156 PACRUNNER_INTERFACE, "DestroyProxyConfiguration");
160 dbus_message_set_auto_start(msg, FALSE);
162 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, ¤t_config,
165 result = dbus_connection_send_with_reply(connection, msg,
166 &call, DBUS_TIMEOUT);
168 dbus_message_unref(msg);
170 if (result == FALSE || call == NULL)
173 dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL);
175 dbus_pending_call_unref(call);
177 g_free(current_config);
178 current_config = NULL;
181 static void default_service_changed(struct connman_service *service)
186 DBG("service %p", service);
188 if (service == default_service)
191 default_service = service;
193 destroy_proxy_configuration();
195 interface = connman_service_get_interface(service);
197 url = connman_service_get_proxy_autoconfig(service);
198 create_proxy_configuration(interface, url);
203 static struct connman_notifier pacrunner_notifier = {
205 .default_changed = default_service_changed,
208 static void pacrunner_connect(DBusConnection *conn, void *user_data)
215 interface = connman_service_get_interface(default_service);
217 url = connman_service_get_proxy_autoconfig(default_service);
218 create_proxy_configuration(interface, url);
223 static void pacrunner_disconnect(DBusConnection *conn, void *user_data)
227 g_free(current_config);
228 current_config = NULL;
231 static guint pacrunner_watch;
233 static int pacrunner_init(void)
235 connection = connman_dbus_get_connection();
236 if (connection == NULL)
239 pacrunner_watch = g_dbus_add_service_watch(connection,
240 PACRUNNER_SERVICE, pacrunner_connect,
241 pacrunner_disconnect, NULL, NULL);
242 if (pacrunner_watch == 0) {
243 dbus_connection_unref(connection);
247 connman_notifier_register(&pacrunner_notifier);
252 static void pacrunner_exit(void)
254 connman_notifier_unregister(&pacrunner_notifier);
256 g_dbus_remove_watch(connection, pacrunner_watch);
258 destroy_proxy_configuration();
260 dbus_connection_unref(connection);
263 CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION,
264 CONNMAN_PLUGIN_PRIORITY_DEFAULT, pacrunner_init, pacrunner_exit)