5 * Copyright (C) 2007-2012 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
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/plugin.h>
33 #include <connman/notifier.h>
34 #include <connman/dbus.h>
35 #include <connman/log.h>
36 #include <connman/proxy.h>
38 #define PACRUNNER_SERVICE "org.pacrunner"
39 #define PACRUNNER_INTERFACE "org.pacrunner.Manager"
40 #define PACRUNNER_PATH "/org/pacrunner/manager"
42 #define PACRUNNER_CLIENT_INTERFACE "org.pacrunner.Client"
43 #define PACRUNNER_CLIENT_PATH "/org/pacrunner/client"
45 #define DBUS_TIMEOUT 5000
48 struct connman_service *service;
52 static DBusConnection *connection;
53 static dbus_bool_t daemon_running = FALSE;
55 static struct connman_service *default_service = NULL;
56 static char *current_config = NULL;
58 static void create_config_reply(DBusPendingCall *call, void *user_data)
60 DBusMessage *reply = dbus_pending_call_steal_reply(call);
65 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
66 connman_error("Failed to create proxy configuration");
70 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
71 DBUS_TYPE_INVALID) == FALSE)
74 g_free(current_config);
75 current_config = g_strdup(path);
78 dbus_message_unref(reply);
81 static void append_string(DBusMessageIter *iter, void *user_data)
83 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
86 static void append_string_list(DBusMessageIter *iter, void *user_data)
88 char **list = user_data;
91 for (i = 0; list[i] != NULL; i++)
92 dbus_message_iter_append_basic(iter,
93 DBUS_TYPE_STRING, &list[i]);
96 static void create_proxy_configuration(void)
99 DBusMessageIter iter, dict;
100 DBusPendingCall *call;
107 if (default_service == NULL)
112 msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
113 PACRUNNER_INTERFACE, "CreateProxyConfiguration");
117 dbus_message_set_auto_start(msg, FALSE);
119 dbus_message_iter_init_append(msg, &iter);
120 connman_dbus_dict_open(&iter, &dict);
122 switch(connman_service_get_proxy_method(default_service)) {
123 case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
124 connman_dbus_dict_close(&iter, &dict);
126 case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
129 case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
132 str_list = connman_service_get_proxy_servers(default_service);
133 if (str_list == NULL) {
134 connman_dbus_dict_close(&iter, &dict);
138 connman_dbus_dict_append_array(&dict, "Servers",
139 DBUS_TYPE_STRING, append_string_list,
141 g_strfreev(str_list);
143 str_list = connman_service_get_proxy_excludes(default_service);
144 if (str_list == NULL)
147 connman_dbus_dict_append_array(&dict, "Excludes",
148 DBUS_TYPE_STRING, append_string_list,
150 g_strfreev(str_list);
153 case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
156 str = connman_service_get_proxy_url(default_service);
158 str = connman_service_get_proxy_autoconfig(
161 connman_dbus_dict_close(&iter, &dict);
166 connman_dbus_dict_append_basic(&dict, "URL",
167 DBUS_TYPE_STRING, &str);
171 connman_dbus_dict_append_basic(&dict, "Method",
172 DBUS_TYPE_STRING, &method);
174 interface = connman_service_get_interface(default_service);
175 if (interface != NULL) {
176 connman_dbus_dict_append_basic(&dict, "Interface",
177 DBUS_TYPE_STRING, &interface);
181 str = connman_service_get_domainname(default_service);
183 connman_dbus_dict_append_array(&dict, "Domains",
184 DBUS_TYPE_STRING, append_string, &str);
186 str_list = connman_service_get_nameservers(default_service);
187 if (str_list != NULL)
188 connman_dbus_dict_append_array(&dict, "Nameservers",
189 DBUS_TYPE_STRING, append_string_list,
191 g_strfreev(str_list);
193 connman_dbus_dict_close(&iter, &dict);
195 result = dbus_connection_send_with_reply(connection, msg,
196 &call, DBUS_TIMEOUT);
198 if (result == FALSE || call == NULL)
201 dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);
203 dbus_pending_call_unref(call);
206 dbus_message_unref(msg);
209 static void destroy_config_reply(DBusPendingCall *call, void *user_data)
211 DBusMessage *reply = dbus_pending_call_steal_reply(call);
215 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
216 connman_error("Failed to destoy proxy configuration");
218 dbus_message_unref(reply);
221 static void destroy_proxy_configuration(void)
224 DBusPendingCall *call;
227 if (current_config == NULL)
232 msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
233 PACRUNNER_INTERFACE, "DestroyProxyConfiguration");
237 dbus_message_set_auto_start(msg, FALSE);
239 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, ¤t_config,
242 result = dbus_connection_send_with_reply(connection, msg,
243 &call, DBUS_TIMEOUT);
245 dbus_message_unref(msg);
247 if (result == FALSE || call == NULL)
250 dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL);
252 dbus_pending_call_unref(call);
254 g_free(current_config);
255 current_config = NULL;
258 static void default_service_changed(struct connman_service *service)
260 DBG("service %p", service);
262 if (service == default_service)
265 default_service = service;
267 if (daemon_running == FALSE)
270 destroy_proxy_configuration();
272 create_proxy_configuration();
275 static void proxy_changed(struct connman_service *service)
277 DBG("service %p", service);
279 if (service != default_service)
282 if (daemon_running == FALSE)
285 destroy_proxy_configuration();
287 create_proxy_configuration();
290 static struct connman_notifier pacrunner_notifier = {
292 .default_changed = default_service_changed,
293 .proxy_changed = proxy_changed,
296 static void pacrunner_connect(DBusConnection *conn, void *user_data)
300 daemon_running = TRUE;
302 create_proxy_configuration();
305 static void pacrunner_disconnect(DBusConnection *conn, void *user_data)
309 daemon_running = FALSE;
311 g_free(current_config);
312 current_config = NULL;
315 static char * parse_url(const char *url)
317 char *scheme, *host, *path, *host_ret;
319 scheme = g_strdup(url);
323 host = strstr(scheme, "://");
330 path = strchr(host, '/');
334 host_ret = g_strdup(host);
341 static void request_lookup_reply(DBusPendingCall *call, void *user_data)
343 DBusMessage *reply = dbus_pending_call_steal_reply(call);
344 struct proxy_data *data = user_data;
349 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
350 connman_error("Failed to find URL:%s", data->url);
355 if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &proxy,
356 DBUS_TYPE_INVALID) == FALSE)
360 connman_proxy_driver_lookup_notify(data->service, data->url, proxy);
362 connman_service_unref(data->service);
367 dbus_message_unref(reply);
370 static int request_lookup(struct connman_service *service, const char *url)
373 DBusPendingCall *call;
376 struct proxy_data *data;
380 if (daemon_running == FALSE)
383 msg = dbus_message_new_method_call(PACRUNNER_SERVICE,
384 PACRUNNER_CLIENT_PATH,
385 PACRUNNER_CLIENT_INTERFACE,
390 host = parse_url(url);
392 dbus_message_unref(msg);
396 data = g_try_new0(struct proxy_data, 1);
398 dbus_message_unref(msg);
403 data->url = g_strdup(url);
404 data->service = connman_service_ref(service);
406 dbus_message_set_auto_start(msg, FALSE);
408 dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
409 DBUS_TYPE_STRING, &host,
412 result = dbus_connection_send_with_reply(connection, msg,
413 &call, DBUS_TIMEOUT);
415 dbus_message_unref(msg);
417 if (result == FALSE || call == NULL) {
424 dbus_pending_call_set_notify(call, request_lookup_reply,
427 dbus_pending_call_unref(call);
433 static void cancel_lookup(struct connman_service *service, const char *url)
438 static struct connman_proxy_driver pacrunner_proxy = {
439 .name = "pacrunnerproxy",
440 .priority = CONNMAN_PROXY_PRIORITY_HIGH,
441 .request_lookup = request_lookup,
442 .cancel_lookup = cancel_lookup,
445 static guint pacrunner_watch;
447 static int pacrunner_init(void)
449 connection = connman_dbus_get_connection();
450 if (connection == NULL)
453 pacrunner_watch = g_dbus_add_service_watch(connection,
454 PACRUNNER_SERVICE, pacrunner_connect,
455 pacrunner_disconnect, NULL, NULL);
456 if (pacrunner_watch == 0) {
457 dbus_connection_unref(connection);
461 connman_notifier_register(&pacrunner_notifier);
463 connman_proxy_driver_register(&pacrunner_proxy);
468 static void pacrunner_exit(void)
470 connman_proxy_driver_unregister(&pacrunner_proxy);
472 connman_notifier_unregister(&pacrunner_notifier);
474 g_dbus_remove_watch(connection, pacrunner_watch);
476 destroy_proxy_configuration();
478 dbus_connection_unref(connection);
481 CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION,
482 CONNMAN_PLUGIN_PRIORITY_DEFAULT, pacrunner_init, pacrunner_exit)