pacrunner: Implement proxy_changed hook
[platform/upstream/connman.git] / plugins / pacrunner.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27
28 #include <gdbus.h>
29
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>
35
36 #define PACRUNNER_SERVICE       "org.pacrunner"
37 #define PACRUNNER_INTERFACE     "org.pacrunner.Manager"
38 #define PACRUNNER_PATH          "/org/pacrunner/manager"
39
40 #define DBUS_TIMEOUT    5000
41
42 static DBusConnection *connection;
43 static dbus_bool_t daemon_running = FALSE;
44
45 static struct connman_service *default_service = NULL;
46 static char *current_config = NULL;
47
48 static void create_config_reply(DBusPendingCall *call, void *user_data)
49 {
50         DBusMessage *reply = dbus_pending_call_steal_reply(call);
51         const char *path;
52
53         DBG("");
54
55         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
56                 connman_error("Failed to create proxy configuration");
57                 goto done;
58         }
59
60         if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
61                                                 DBUS_TYPE_INVALID) == FALSE)
62                 goto done;
63
64         g_free(current_config);
65         current_config = g_strdup(path);
66
67 done:
68         dbus_message_unref(reply);
69 }
70
71 static void append_string(DBusMessageIter *iter, void *user_data)
72 {
73         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
74 }
75
76 static void append_string_list(DBusMessageIter *iter, void *user_data)
77 {
78         char **list = user_data;
79         int i;
80
81         for (i = 0; list[i] != NULL; i++)
82                 dbus_message_iter_append_basic(iter,
83                                         DBUS_TYPE_STRING, &list[i]);
84 }
85
86 static void create_proxy_configuration(void)
87 {
88         DBusMessage *msg;
89         DBusMessageIter iter, dict;
90         DBusPendingCall *call;
91         dbus_bool_t result;
92         char *interface;
93         const char *method;
94         const char *str;
95         char **str_list;
96
97         if (default_service == NULL)
98                 return;
99
100         DBG("");
101
102         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
103                         PACRUNNER_INTERFACE, "CreateProxyConfiguration");
104         if (msg == NULL)
105                 return;
106
107         dbus_message_set_auto_start(msg, FALSE);
108
109         dbus_message_iter_init_append(msg, &iter);
110         connman_dbus_dict_open(&iter, &dict);
111
112         switch(connman_service_get_proxy_method(default_service)) {
113         case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN:
114                 goto done;
115         case CONNMAN_SERVICE_PROXY_METHOD_DIRECT:
116                 method= "direct";
117                 break;
118         case CONNMAN_SERVICE_PROXY_METHOD_MANUAL:
119                 method = "manual";
120
121                 str_list = connman_service_get_proxy_servers(default_service);
122                 if (str_list == NULL)
123                         goto done;
124
125                 connman_dbus_dict_append_array(&dict, "Servers",
126                                         DBUS_TYPE_STRING, append_string_list,
127                                         str_list);
128                 g_strfreev(str_list);
129
130                 str_list = connman_service_get_proxy_excludes(default_service);
131                 if (str_list == NULL)
132                         break;
133
134                 connman_dbus_dict_append_array(&dict, "Excludes",
135                                         DBUS_TYPE_STRING, append_string_list,
136                                         str_list);
137                 g_strfreev(str_list);
138
139                 break;
140         case CONNMAN_SERVICE_PROXY_METHOD_AUTO:
141                 method = "auto";
142
143                 str = connman_service_get_proxy_url(default_service);
144                 if (str == NULL) {
145                         str = connman_service_get_proxy_autoconfig(
146                                                         default_service);
147                         if (str == NULL)
148                                 goto done;
149                 }
150
151                 connman_dbus_dict_append_basic(&dict, "URL",
152                                         DBUS_TYPE_STRING, &str);
153                 break;
154         }
155
156         connman_dbus_dict_append_basic(&dict, "Method",
157                                 DBUS_TYPE_STRING, &method);
158
159         interface = connman_service_get_interface(default_service);
160         if (interface != NULL) {
161                 connman_dbus_dict_append_basic(&dict, "Interface",
162                                                 DBUS_TYPE_STRING, &interface);
163                 g_free(interface);
164         }
165
166         str = connman_service_get_domainname(default_service);
167         if (str != NULL)
168                 connman_dbus_dict_append_array(&dict, "Domains",
169                                         DBUS_TYPE_STRING, append_string, &str);
170
171         str = connman_service_get_nameserver(default_service);
172         if (str != NULL)
173                 connman_dbus_dict_append_array(&dict, "Nameservers",
174                                         DBUS_TYPE_STRING, append_string, &str);
175
176         connman_dbus_dict_close(&iter, &dict);
177
178         result = dbus_connection_send_with_reply(connection, msg,
179                                                         &call, DBUS_TIMEOUT);
180
181         if (result == FALSE || call == NULL)
182                 goto done;
183
184         dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);
185
186         dbus_pending_call_unref(call);
187
188 done:
189         dbus_message_unref(msg);
190 }
191
192 static void destroy_config_reply(DBusPendingCall *call, void *user_data)
193 {
194         DBusMessage *reply = dbus_pending_call_steal_reply(call);
195
196         DBG("");
197
198         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
199                 connman_error("Failed to destoy proxy configuration");
200
201         dbus_message_unref(reply);
202 }
203
204 static void destroy_proxy_configuration(void)
205 {
206         DBusMessage *msg;
207         DBusPendingCall *call;
208         dbus_bool_t result;
209
210         if (current_config == NULL)
211                 return;
212
213         DBG("");
214
215         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
216                         PACRUNNER_INTERFACE, "DestroyProxyConfiguration");
217         if (msg == NULL)
218                 return;
219
220         dbus_message_set_auto_start(msg, FALSE);
221
222         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &current_config,
223                                                         DBUS_TYPE_INVALID);
224
225         result = dbus_connection_send_with_reply(connection, msg,
226                                                         &call, DBUS_TIMEOUT);
227
228         dbus_message_unref(msg);
229
230         if (result == FALSE || call == NULL)
231                 return;
232
233         dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL);
234
235         dbus_pending_call_unref(call);
236
237         g_free(current_config);
238         current_config = NULL;
239 }
240
241 static void default_service_changed(struct connman_service *service)
242 {
243         DBG("service %p", service);
244
245         if (service == default_service)
246                 return;
247
248         default_service = service;
249
250         if (daemon_running == FALSE)
251                 return;
252
253         destroy_proxy_configuration();
254
255         create_proxy_configuration();
256 }
257
258 static void proxy_changed(struct connman_service *service)
259 {
260         DBG("service %p", service);
261
262         if (service != default_service)
263                 return;
264
265         if (daemon_running == FALSE)
266                 return;
267
268         destroy_proxy_configuration();
269
270         create_proxy_configuration();
271 }
272
273 static struct connman_notifier pacrunner_notifier = {
274         .name                   = "pacrunner",
275         .default_changed        = default_service_changed,
276         .proxy_changed          = proxy_changed,
277 };
278
279 static void pacrunner_connect(DBusConnection *conn, void *user_data)
280 {
281         DBG("");
282
283         daemon_running = TRUE;
284
285         create_proxy_configuration();
286 }
287
288 static void pacrunner_disconnect(DBusConnection *conn, void *user_data)
289 {
290         DBG("");
291
292         daemon_running = FALSE;
293
294         g_free(current_config);
295         current_config = NULL;
296 }
297
298 static guint pacrunner_watch;
299
300 static int pacrunner_init(void)
301 {
302         connection = connman_dbus_get_connection();
303         if (connection == NULL)
304                 return -EIO;
305
306         pacrunner_watch = g_dbus_add_service_watch(connection,
307                                         PACRUNNER_SERVICE, pacrunner_connect,
308                                         pacrunner_disconnect, NULL, NULL);
309         if (pacrunner_watch == 0) {
310                 dbus_connection_unref(connection);
311                 return -EIO;
312         }
313
314         connman_notifier_register(&pacrunner_notifier);
315
316         return 0;
317 }
318
319 static void pacrunner_exit(void)
320 {
321         connman_notifier_unregister(&pacrunner_notifier);
322
323         g_dbus_remove_watch(connection, pacrunner_watch);
324
325         destroy_proxy_configuration();
326
327         dbus_connection_unref(connection);
328 }
329
330 CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION,
331                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, pacrunner_init, pacrunner_exit)