Add interface string to proxy configuration
[framework/connectivity/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
44 static struct connman_service *default_service = NULL;
45 static char *current_config = NULL;
46
47 static void create_config_reply(DBusPendingCall *call, void *user_data)
48 {
49         DBusMessage *reply = dbus_pending_call_steal_reply(call);
50         const char *path;
51
52         DBG("");
53
54         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
55                 connman_error("Failed to create proxy configuration");
56                 goto done;
57         }
58
59         if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
60                                                 DBUS_TYPE_INVALID) == FALSE)
61                 goto done;
62
63         g_free(current_config);
64         current_config = g_strdup(path);
65
66 done:
67         dbus_message_unref(reply);
68 }
69
70 static void add_string_entry(DBusMessageIter *iter,
71                                         const char *key, const char *str)
72 {
73         DBusMessageIter value;
74
75         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
76
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);
81 }
82
83 static void create_proxy_configuration(const char *interface, const char *url)
84 {
85         DBusMessage *msg;
86         DBusMessageIter iter, dict, entry;
87         DBusPendingCall *call;
88         dbus_bool_t result;
89
90         if (url == NULL)
91                 return;
92
93         DBG("interface %s url %s", interface, url);
94
95         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
96                         PACRUNNER_INTERFACE, "CreateProxyConfiguration");
97         if (msg == NULL)
98                 return;
99
100         dbus_message_set_auto_start(msg, FALSE);
101
102         dbus_message_iter_init_append(msg, &iter);
103
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,
109                                                                 NULL, &entry);
110
111         if (interface != NULL)
112                 add_string_entry(&entry, "Interface", interface);
113
114         add_string_entry(&entry, "URL", url);
115
116         dbus_message_iter_close_container(&dict, &entry);
117         dbus_message_iter_close_container(&iter, &dict);
118
119         result = dbus_connection_send_with_reply(connection, msg,
120                                                         &call, DBUS_TIMEOUT);
121
122         dbus_message_unref(msg);
123
124         if (result == FALSE || call == NULL)
125                 return;
126
127         dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);
128
129         dbus_pending_call_unref(call);
130 }
131
132 static void destroy_config_reply(DBusPendingCall *call, void *user_data)
133 {
134         DBusMessage *reply = dbus_pending_call_steal_reply(call);
135
136         DBG("");
137
138         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
139                 connman_error("Failed to destoy proxy configuration");
140
141         dbus_message_unref(reply);
142 }
143
144 static void destroy_proxy_configuration(void)
145 {
146         DBusMessage *msg;
147         DBusPendingCall *call;
148         dbus_bool_t result;
149
150         if (current_config == NULL)
151                 return;
152
153         DBG("");
154
155         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
156                         PACRUNNER_INTERFACE, "DestroyProxyConfiguration");
157         if (msg == NULL)
158                 return;
159
160         dbus_message_set_auto_start(msg, FALSE);
161
162         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &current_config,
163                                                         DBUS_TYPE_INVALID);
164
165         result = dbus_connection_send_with_reply(connection, msg,
166                                                         &call, DBUS_TIMEOUT);
167
168         dbus_message_unref(msg);
169
170         if (result == FALSE || call == NULL)
171                 return;
172
173         dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL);
174
175         dbus_pending_call_unref(call);
176
177         g_free(current_config);
178         current_config = NULL;
179 }
180
181 static void default_service_changed(struct connman_service *service)
182 {
183         char *interface;
184         const char *url;
185
186         DBG("service %p", service);
187
188         if (service == default_service)
189                 return;
190
191         default_service = service;
192
193         destroy_proxy_configuration();
194
195         interface = connman_service_get_interface(service);
196
197         url = connman_service_get_proxy_autoconfig(service);
198         create_proxy_configuration(interface, url);
199
200         g_free(interface);
201 }
202
203 static struct connman_notifier pacrunner_notifier = {
204         .name                   = "pacrunner",
205         .default_changed        = default_service_changed,
206 };
207
208 static void pacrunner_connect(DBusConnection *conn, void *user_data)
209 {
210         char *interface;
211         const char *url;
212
213         DBG("");
214
215         interface = connman_service_get_interface(default_service);
216
217         url = connman_service_get_proxy_autoconfig(default_service);
218         create_proxy_configuration(interface, url);
219
220         g_free(interface);
221 }
222
223 static void pacrunner_disconnect(DBusConnection *conn, void *user_data)
224 {
225         DBG("");
226
227         g_free(current_config);
228         current_config = NULL;
229 }
230
231 static guint pacrunner_watch;
232
233 static int pacrunner_init(void)
234 {
235         connection = connman_dbus_get_connection();
236         if (connection == NULL)
237                 return -EIO;
238
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);
244                 return -EIO;
245         }
246
247         connman_notifier_register(&pacrunner_notifier);
248
249         return 0;
250 }
251
252 static void pacrunner_exit(void)
253 {
254         connman_notifier_unregister(&pacrunner_notifier);
255
256         g_dbus_remove_watch(connection, pacrunner_watch);
257
258         destroy_proxy_configuration();
259
260         dbus_connection_unref(connection);
261 }
262
263 CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION,
264                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, pacrunner_init, pacrunner_exit)