Imported Upstream version 1.37
[platform/upstream/connman.git] / src / proxy.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  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 <glib.h>
27
28 #include "connman.h"
29
30 static unsigned int next_lookup_token = 1;
31
32 static GSList *driver_list = NULL;
33 static GSList *lookup_list = NULL;
34
35 struct proxy_lookup {
36         unsigned int token;
37         connman_proxy_lookup_cb cb;
38         void *user_data;
39         struct connman_service *service;
40         char *url;
41         guint watch;
42         struct connman_proxy_driver *proxy;
43 };
44
45 static void remove_lookup(struct proxy_lookup *lookup)
46 {
47         if (lookup->watch > 0)
48                 g_source_remove(lookup->watch);
49
50         lookup_list = g_slist_remove(lookup_list, lookup);
51
52         connman_service_unref(lookup->service);
53         g_free(lookup->url);
54         g_free(lookup);
55 }
56
57 static void remove_lookups(GSList *lookups)
58 {
59         GSList *list;
60
61         for (list = lookups; list; list = list->next) {
62                 struct proxy_lookup *lookup = list->data;
63
64                 remove_lookup(lookup);
65         }
66
67         g_slist_free(lookups);
68 }
69
70 static gboolean lookup_callback(gpointer user_data)
71 {
72         struct proxy_lookup *lookup = user_data;
73         GSList *list;
74
75         if (!lookup)
76                 return FALSE;
77
78         lookup->watch = 0;
79
80         for (list = driver_list; list; list = list->next) {
81                 struct connman_proxy_driver *proxy = list->data;
82
83                 if (!proxy->request_lookup)
84                         continue;
85
86                 lookup->proxy = proxy;
87                 break;
88         }
89
90         if (!lookup->proxy ||
91                 lookup->proxy->request_lookup(lookup->service,
92                                                 lookup->url) < 0) {
93
94                 if (lookup->cb)
95                         lookup->cb(NULL, lookup->user_data);
96
97                 remove_lookup(lookup);
98         }
99
100         return FALSE;
101 }
102
103 unsigned int connman_proxy_lookup(const char *interface, const char *url,
104                                         struct connman_service *service,
105                                         connman_proxy_lookup_cb cb,
106                                         void *user_data)
107 {
108         struct proxy_lookup *lookup;
109
110         DBG("interface %s url %s", interface, url);
111
112         if (!interface)
113                 return 0;
114
115         lookup = g_try_new0(struct proxy_lookup, 1);
116         if (!lookup)
117                 return 0;
118
119         lookup->token = next_lookup_token++;
120
121         lookup->cb = cb;
122         lookup->user_data = user_data;
123         lookup->url = g_strdup(url);
124         lookup->service = connman_service_ref(service);
125
126         lookup->watch = g_idle_add(lookup_callback, lookup);
127         if (lookup->watch == 0) {
128                 g_free(lookup->url);
129                 g_free(lookup);
130                 return 0;
131         }
132
133         DBG("token %u", lookup->token);
134         lookup_list = g_slist_prepend(lookup_list, lookup);
135
136         return lookup->token;
137 }
138
139 void connman_proxy_lookup_cancel(unsigned int token)
140 {
141         GSList *list;
142         struct proxy_lookup *lookup = NULL;
143
144         DBG("token %u", token);
145
146         for (list = lookup_list; list; list = list->next) {
147                 lookup = list->data;
148
149                 if (lookup->token == token)
150                         break;
151
152                 lookup = NULL;
153         }
154
155         if (lookup) {
156                 if (lookup->proxy &&
157                                         lookup->proxy->cancel_lookup)
158                         lookup->proxy->cancel_lookup(lookup->service,
159                                                                 lookup->url);
160
161                 remove_lookup(lookup);
162         }
163 }
164
165 void connman_proxy_driver_lookup_notify(struct connman_service *service,
166                                         const char *url, const char *result)
167 {
168         GSList *list, *matches = NULL;
169
170         DBG("service %p url %s result %s", service, url, result);
171
172         for (list = lookup_list; list; list = list->next) {
173                 struct proxy_lookup *lookup = list->data;
174
175                 if (service != lookup->service)
176                         continue;
177
178                 if (g_strcmp0(lookup->url, url) == 0) {
179                         if (lookup->cb)
180                                 lookup->cb(result, lookup->user_data);
181
182                         matches = g_slist_prepend(matches, lookup);
183                 }
184         }
185
186         if (matches)
187                 remove_lookups(matches);
188 }
189
190 static gint compare_priority(gconstpointer a, gconstpointer b)
191 {
192         const struct connman_proxy_driver *driver1 = a;
193         const struct connman_proxy_driver *driver2 = b;
194
195         return driver2->priority - driver1->priority;
196 }
197
198 /**
199  * connman_proxy_driver_register:
200  * @driver: Proxy driver definition
201  *
202  * Register a new proxy driver
203  *
204  * Returns: %0 on success
205  */
206 int connman_proxy_driver_register(struct connman_proxy_driver *driver)
207 {
208         DBG("driver %p name %s", driver, driver->name);
209
210         driver_list = g_slist_insert_sorted(driver_list, driver,
211                                                         compare_priority);
212
213         return 0;
214 }
215
216 /**
217  * connman_proxy_driver_unregister:
218  * @driver: Proxy driver definition
219  *
220  * Remove a previously registered proxy driver
221  */
222 void connman_proxy_driver_unregister(struct connman_proxy_driver *driver)
223 {
224         GSList *list;
225
226         DBG("driver %p name %s", driver, driver->name);
227
228         driver_list = g_slist_remove(driver_list, driver);
229
230         for (list = lookup_list; list; list = list->next) {
231                 struct proxy_lookup *lookup = list->data;
232
233                 if (lookup->proxy == driver)
234                         lookup->proxy = NULL;
235         }
236
237 }
238
239 int __connman_proxy_init(void)
240 {
241         DBG("");
242
243         return 0;
244 }
245
246 void __connman_proxy_cleanup(void)
247 {
248         DBG("");
249
250         remove_lookups(lookup_list);
251 }