blob: b6775b6748903c7c8fa2891b7bc221b4430cc962 [file] [log] [blame] [edit]
/*
*
* Connection Manager
*
* Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include "connman.h"
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);
connman_service_unref(lookup->service);
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;
for (list = driver_list; list; list = list->next) {
struct connman_proxy_driver *proxy = list->data;
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,
struct connman_service *service,
connman_proxy_lookup_cb cb,
void *user_data)
{
struct proxy_lookup *lookup;
DBG("interface %s url %s", interface, url);
if (interface == NULL)
return 0;
lookup = g_try_new0(struct proxy_lookup, 1);
if (lookup == NULL)
return 0;
lookup->token = next_lookup_token++;
lookup->cb = cb;
lookup->user_data = user_data;
lookup->url = g_strdup(url);
lookup->service = connman_service_ref(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_prepend(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;
lookup = NULL;
}
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);
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_prepend(matches, lookup);
}
}
if (matches != NULL)
remove_lookups(matches);
}
static gint compare_priority(gconstpointer a, gconstpointer b)
{
const struct connman_proxy_driver *driver1 = a;
const struct connman_proxy_driver *driver2 = b;
return driver2->priority - driver1->priority;
}
/**
* connman_proxy_driver_register:
* @driver: Proxy driver definition
*
* Register a new proxy driver
*
* Returns: %0 on success
*/
int connman_proxy_driver_register(struct connman_proxy_driver *driver)
{
DBG("driver %p name %s", driver, driver->name);
driver_list = g_slist_insert_sorted(driver_list, driver,
compare_priority);
return 0;
}
/**
* connman_proxy_driver_unregister:
* @driver: Proxy driver definition
*
* Remove a previously registered proxy driver
*/
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)
{
DBG("");
return 0;
}
void __connman_proxy_cleanup(void)
{
DBG("");
remove_lookups(lookup_list);
}