#define STATUS_URL "http://www.connman.net/online/status.html"
struct server_data {
+ unsigned int token;
GWeb *web;
guint request_id;
};
proxy = getenv("http_proxy");
if (data != NULL) {
- g_web_set_proxy(data->web, proxy);
+ if (proxy != NULL && g_strcmp0(proxy, "DIRECT") != 0)
+ g_web_set_proxy(data->web, proxy);
data->request_id = g_web_request_get(data->web, STATUS_URL,
web_result, location);
+
+ data->token = 0;
}
connman_location_unref(location);
static int location_detect(struct connman_location *location)
{
struct server_data *data;
+ struct connman_service *service;
enum connman_service_type service_type;
char *interface;
int err;
g_web_set_user_agent(data->web, "ConnMan/%s", VERSION);
g_web_set_close_connection(data->web, TRUE);
- err = connman_proxy_lookup(interface, STATUS_URL,
- proxy_callback, location);
- if (err < 0)
- goto done;
-
connman_location_ref(location);
- err = 0;
+
+ service = connman_location_get_service(location);
+ data->token = connman_proxy_lookup(interface, STATUS_URL,
+ service, proxy_callback, location);
+
+ if (data->token == 0) {
+ connman_location_unref(location);
+ err = -EINVAL;
+ } else
+ err = 0;
done:
g_free(interface);
if (data->request_id > 0)
g_web_cancel_request(data->web, data->request_id);
+ if (data->token > 0) {
+ connman_proxy_lookup_cancel(data->token);
+ connman_location_unref(location);
+ }
+
g_web_unref(data->web);
g_free(data);
static unsigned int next_lookup_token = 1;
static GSList *driver_list = NULL;
+static GSList *lookup_list = NULL;
struct proxy_lookup {
unsigned int token;
connman_proxy_lookup_cb cb;
void *user_data;
+ struct connman_service *service;
+ char *url;
guint watch;
+ struct connman_proxy_driver *proxy;
};
+static void remove_lookup(struct proxy_lookup *lookup)
+{
+ lookup_list = g_slist_remove(lookup_list, lookup);
+
+ g_free(lookup->url);
+ g_free(lookup);
+}
+
+static void remove_lookups(GSList *lookups)
+{
+ GSList *list;
+
+ for (list = lookups; list; list = list->next) {
+ struct proxy_lookup *lookup = list->data;
+
+ remove_lookup(lookup);
+ }
+
+ g_slist_free(lookups);
+}
+
static gboolean lookup_callback(gpointer user_data)
{
struct proxy_lookup *lookup = user_data;
+ GSList *list;
+
+ if (lookup == NULL)
+ return FALSE;
lookup->watch = 0;
- if (lookup->cb)
- lookup->cb(NULL, lookup->user_data);
+ for (list = driver_list; list; list = list->next) {
+ struct connman_proxy_driver *proxy = list->data;
- g_free(lookup);
+ if (proxy->request_lookup == NULL)
+ continue;
+
+ lookup->proxy = proxy;
+ break;
+ }
+
+ if (lookup->proxy == NULL ||
+ lookup->proxy->request_lookup(lookup->service,
+ lookup->url) < 0) {
+
+ if (lookup->cb)
+ lookup->cb(NULL, lookup->user_data);
+
+ remove_lookup(lookup);
+ }
return FALSE;
}
unsigned int connman_proxy_lookup(const char *interface, const char *url,
- connman_proxy_lookup_cb cb, void *user_data)
+ struct connman_service *service,
+ connman_proxy_lookup_cb cb,
+ void *user_data)
{
struct proxy_lookup *lookup;
lookup->cb = cb;
lookup->user_data = user_data;
+ lookup->url = g_strdup(url);
+ lookup->service = service;
lookup->watch = g_timeout_add_seconds(0, lookup_callback, lookup);
if (lookup->watch == 0) {
+ g_free(lookup->url);
g_free(lookup);
return 0;
}
DBG("token %u", lookup->token);
+ lookup_list = g_slist_append(lookup_list, lookup);
return lookup->token;
}
void connman_proxy_lookup_cancel(unsigned int token)
{
+ GSList *list;
+ struct proxy_lookup *lookup = NULL;
+
DBG("token %u", token);
+
+ for (list = lookup_list; list; list = list->next) {
+ lookup = list->data;
+
+ if (lookup->token == token)
+ break;
+ }
+
+ if (lookup != NULL) {
+ if (lookup->watch > 0) {
+ g_source_remove(lookup->watch);
+ lookup->watch = 0;
+ }
+
+ if (lookup->proxy != NULL &&
+ lookup->proxy->cancel_lookup != NULL)
+ lookup->proxy->cancel_lookup(lookup->service,
+ lookup->url);
+
+ remove_lookup(lookup);
+ }
}
void connman_proxy_driver_lookup_notify(struct connman_service *service,
const char *url, const char *result)
{
+ GSList *list, *matches = NULL;
+
DBG("service %p url %s result %s", service, url, result);
- if (service == NULL)
- return;
+ for (list = lookup_list; list; list = list->next) {
+ struct proxy_lookup *lookup = list->data;
+
+ if (service != lookup->service)
+ continue;
+
+ if (g_strcmp0(lookup->url, url) == 0) {
+ if (lookup->cb)
+ lookup->cb(result, lookup->user_data);
+
+ matches = g_slist_append(matches, lookup);
+ }
+ }
+
+ if (matches != NULL)
+ remove_lookups(matches);
}
static gint compare_priority(gconstpointer a, gconstpointer b)
*/
void connman_proxy_driver_unregister(struct connman_proxy_driver *driver)
{
+ GSList *list;
+
DBG("driver %p name %s", driver, driver->name);
driver_list = g_slist_remove(driver_list, driver);
+
+ for (list = lookup_list; list; list = list->next) {
+ struct proxy_lookup *lookup = list->data;
+
+ if (lookup->proxy == driver)
+ lookup->proxy = NULL;
+ }
+
}
int __connman_proxy_init(void)
void __connman_proxy_cleanup(void)
{
DBG("");
+
+ remove_lookups(lookup_list);
}