summaryrefslogtreecommitdiff
path: root/src/lib/proxy_factory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/proxy_factory.c')
-rw-r--r--src/lib/proxy_factory.c402
1 files changed, 264 insertions, 138 deletions
diff --git a/src/lib/proxy_factory.c b/src/lib/proxy_factory.c
index 1376563..5591c9c 100644
--- a/src/lib/proxy_factory.c
+++ b/src/lib/proxy_factory.c
@@ -34,8 +34,6 @@
#include "proxy_factory.h"
#include "wpad.h"
#include "config_file.h"
-#include "array.h"
-#include "strdict.h"
#define DEFAULT_CONFIG_ORDER "USER,SESSION,SYSTEM"
@@ -46,19 +44,25 @@ struct _pxProxyFactoryConfig {
};
typedef struct _pxProxyFactoryConfig pxProxyFactoryConfig;
+struct _pxKeyVal {
+ char *key;
+ void *value;
+};
+typedef struct _pxKeyVal pxKeyVal;
+
struct _pxProxyFactory {
- pthread_mutex_t mutex;
- pxArray *plugins;
- pxProxyFactoryConfig **configs;
- pxStrDict *misc;
- pxArray *on_get_proxies;
- pxPACRunnerCallback pac_runner;
- pxPAC *pac;
- pxWPAD *wpad;
- pxConfigFile *cf;
+ pthread_mutex_t mutex;
+ void **plugins;
+ pxProxyFactoryConfig **configs;
+ pxKeyVal **misc;
+ pxProxyFactoryVoidCallback *on_get_proxy;
+ pxPACRunnerCallback pac_runner;
+ pxPAC *pac;
+ pxWPAD *wpad;
+ pxConfigFile *cf;
};
-/* Convert the PAC formatted response into our proxy URL array response */
+// Convert the PAC formatted response into our proxy URL array response
static char **
_format_pac_response(char *response)
{
@@ -107,7 +111,7 @@ _sockaddr_equals(const struct sockaddr *ip_a, const struct sockaddr *ip_b, const
if (ip_a->sa_family != ip_b->sa_family) return false;
if (nm && ip_a->sa_family != nm->sa_family) return false;
- /* Setup the arrays */
+ // Setup the arrays
uint8_t bytes = 0, *a_data = NULL, *b_data = NULL, *nm_data = NULL;
if (ip_a->sa_family == AF_INET)
{
@@ -142,26 +146,26 @@ _sockaddr_from_string(const char *ip, int len)
if (!ip) return NULL;
struct sockaddr *result = NULL;
- /* Copy the string */
+ // Copy the string
if (len >= 0)
ip = px_strndup(ip, len);
else
ip = px_strdup(ip);
- /* Try to parse IPv4 */
+ // Try to parse IPv4
result = px_malloc0(sizeof(struct sockaddr_in));
result->sa_family = AF_INET;
if (inet_pton(AF_INET, ip, &((struct sockaddr_in *) result)->sin_addr) > 0)
goto out;
- /* Try to parse IPv6 */
+ // Try to parse IPv6
px_free(result);
result = px_malloc0(sizeof(struct sockaddr_in6));
result->sa_family = AF_INET6;
if (inet_pton(AF_INET6, ip, &((struct sockaddr_in6 *) result)->sin6_addr) > 0)
goto out;
- /* No address found */
+ // No address found
px_free(result);
result = NULL;
out:
@@ -172,7 +176,7 @@ _sockaddr_from_string(const char *ip, int len)
static struct sockaddr *
_sockaddr_from_cidr(int af, int cidr)
{
- /* TODO: Support CIDR notation */
+ // TODO: Support CIDR notation
return NULL;
}
@@ -186,25 +190,21 @@ _ip_ignore(pxURL *url, char *ignore)
const struct sockaddr *dst_ip = px_url_get_ip_no_dns(url);
struct sockaddr *ign_ip = NULL, *net_ip = NULL;
- /*
- * IPv4
- * IPv6
- */
+ // IPv4
+ // IPv6
if ((ign_ip = _sockaddr_from_string(ignore, -1)))
goto out;
- /*
- * IPv4/CIDR
- * IPv4/IPv4
- * IPv6/CIDR
- * IPv6/IPv6
- */
+ // IPv4/CIDR
+ // IPv4/IPv4
+ // IPv6/CIDR
+ // IPv6/IPv6
if (strchr(ignore, '/'))
{
ign_ip = _sockaddr_from_string(ignore, strchr(ignore, '/') - ignore);
net_ip = _sockaddr_from_string(strchr(ignore, '/') + 1, -1);
- /* If CIDR notation was used, get the netmask */
+ // If CIDR notation was used, get the netmask
if (ign_ip && !net_ip)
{
uint32_t cidr = 0;
@@ -221,15 +221,13 @@ _ip_ignore(pxURL *url, char *ignore)
net_ip = NULL;
}
- /*
- * IPv4:port
- * [IPv6]:port
- */
+ // IPv4:port
+ // [IPv6]:port
if (strrchr(ignore, ':') && sscanf(strrchr(ignore, ':'), ":%u", &port) == 1 && port > 0)
{
ign_ip = _sockaddr_from_string(ignore, strrchr(ignore, ':') - ignore);
- /* Make sure this really is just a port and not just an IPv6 address */
+ // Make sure this really is just a port and not just an IPv6 address
if (ign_ip && (ign_ip->sa_family != AF_INET6 || ignore[0] == '['))
goto out;
@@ -251,11 +249,11 @@ _domain_ignore(pxURL *url, char *ignore)
if (!url || !ignore)
return false;
- /* Get our URL's hostname and port */
+ // Get our URL's hostname and port
char *host = px_strdup(px_url_get_host(url));
int port = px_url_get_port(url);
- /* Get our ignore pattern's hostname and port */
+ // Get our ignore pattern's hostname and port
char *ihost = px_strdup(ignore);
int iport = 0;
if (strchr(ihost, ':'))
@@ -267,49 +265,33 @@ _domain_ignore(pxURL *url, char *ignore)
iport = 0;
}
- /* Hostname match (domain.com or domain.com:80) */
+ // Hostname match (domain.com or domain.com:80)
if (!strcmp(host, ihost))
if (!iport || port == iport)
goto match;
- /* Endswith (.domain.com or .domain.com:80) */
+ // Endswith (.domain.com or .domain.com:80)
if (ihost[0] == '.' && _endswith(host, ihost))
if (!iport || port == iport)
goto match;
- /* Glob (*.domain.com or *.domain.com:80) */
+ // Glob (*.domain.com or *.domain.com:80)
if (ihost[0] == '*' && _endswith(host, ihost+1))
if (!iport || port == iport)
goto match;
- /* No match was found */
+ // No match was found
px_free(host);
px_free(ihost);
return false;
- /* A match was found */
+ // A match was found
match:
px_free(host);
px_free(ihost);
return true;
}
-static void
-destantiate_plugins(void *item, void *self)
-{
- /* Call the destantiation hook */
- pxProxyFactoryVoidCallback destantiate;
- destantiate = dlsym(item, "on_proxy_factory_destantiate");
- if (destantiate)
- destantiate(self);
-}
-
-static void
-call_on_proxy_factory_get_proxies(void *item, void *self)
-{
- ((pxProxyFactoryVoidCallback) item)(self);
-}
-
/**
* Creates a new pxProxyFactory instance.
*
@@ -319,33 +301,44 @@ pxProxyFactory *
px_proxy_factory_new ()
{
pxProxyFactory *self = px_malloc0(sizeof(pxProxyFactory));
+ unsigned int i;
+
+ // Create the mutex
pthread_mutex_init(&self->mutex, NULL);
- self->plugins = px_array_new(NULL, (void *) dlclose, true, false);
- self->misc = px_strdict_new(NULL);
- self->on_get_proxies = px_array_new(NULL, NULL, true, false);
- /* Open the plugin dir */
+ // Open the plugin dir
DIR *plugindir = opendir(PLUGINDIR);
if (!plugindir) return self;
- /* For each plugin... */
+ // Count the number of plugins
+ for (i=0 ; readdir(plugindir) ; i++);
+ self->plugins = (void **) px_malloc0(sizeof(void *) * (i + 1));
+ rewinddir(plugindir);
+
+ // For each plugin...
struct dirent *ent;
- for (int i=0 ; (ent = readdir(plugindir)) ; i++)
+ for (i=0 ; (ent = readdir(plugindir)) ; i++)
{
- /* Load the plugin */
+ // Load the plugin
char *tmp = px_strcat(PLUGINDIR, "/", ent->d_name, NULL);
- void *plugin = dlopen(tmp, RTLD_NOW | RTLD_LOCAL);
+ self->plugins[i] = dlopen(tmp, RTLD_NOW | RTLD_LOCAL);
px_free(tmp);
- if (!plugin)
+ if (!(self->plugins[i]))
+ {
+ dlerror();
+ i--;
continue;
+ }
- /* Call the instantiation hook */
+ // Call the instantiation hook
pxProxyFactoryBoolCallback instantiate;
- instantiate = dlsym(plugin, "on_proxy_factory_instantiate");
+ instantiate = dlsym(self->plugins[i], "on_proxy_factory_instantiate");
if (instantiate && !instantiate(self))
- dlclose(plugin);
- else if (instantiate)
- px_array_add(self->plugins, plugin);
+ {
+ dlclose(self->plugins[i]);
+ self->plugins[i--] = NULL;
+ continue;
+ }
}
closedir(plugindir);
@@ -358,29 +351,27 @@ px_proxy_factory_config_add(pxProxyFactory *self, const char *name, pxConfigCate
int count;
pxProxyFactoryConfig **tmp;
- /* Verify some basic stuff */
+ // Verify some basic stuff
if (!self) return false;
if (!callback) return false;
if (!name || !strcmp(name, "")) return false;
- /* Allocate an empty config array if there is none */
+ // Allocate an empty config array if there is none
if (!self->configs) self->configs = px_malloc0(sizeof(pxProxyFactoryConfig *));
- /*
- * Make sure that 'name' is unique
- * Also, get a count of how many configs we have
- */
+ // Make sure that 'name' is unique
+ // Also, get a count of how many configs we have
for (count=0 ; self->configs[count] ; count++)
if (!strcmp(self->configs[count]->name, name))
return false;
- /* Allocate new array, copy old values into it and free old array */
+ // Allocate new array, copy old values into it and free old array
tmp = px_malloc0(sizeof(pxProxyFactoryConfig *) * (count + 2));
memcpy(tmp, self->configs, sizeof(pxProxyFactoryConfig *) * count);
px_free(self->configs);
self->configs = tmp;
- /* Add the new callback to the end */
+ // Add the new callback to the end
self->configs[count] = px_malloc0(sizeof(pxProxyFactoryConfig));
self->configs[count]->category = category;
self->configs[count]->name = px_strdup(name);
@@ -394,12 +385,12 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name)
{
int i,j;
- /* Verify some basic stuff */
+ // Verify some basic stuff
if (!self) return false;
if (!name || !strcmp(name, "")) return false;
if (!self->configs) return false;
- /* Remove and shift all configs down (if found) */
+ // Remove and shift all configs down (if found)
for (i=0,j=0 ; self->configs[j]; i++,j++)
{
if (i != j)
@@ -411,7 +402,7 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name)
}
}
- /* If we have an empty array, free it */
+ // If we have an empty array, free it
if (!self->configs[0])
{
px_free(self->configs);
@@ -424,21 +415,83 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name)
bool
px_proxy_factory_misc_set(pxProxyFactory *self, const char *key, const void *value)
{
- /* Verify some basic stuff */
- if (!self) return false;
- if (!key || !strcmp(key, "")) return false;
-
- return px_strdict_set(self->misc, key, (void *) value);
+ int count;
+ pxKeyVal **tmp;
+
+ // Verify some basic stuff
+ if (!self) return false;
+ if (!key || !strcmp(key, "")) return false;
+
+ // Allocate an empty config array if there is none
+ if (!self->misc) self->misc = px_malloc0(sizeof(pxKeyVal *));
+
+ // Count the number of values
+ for (count=0 ; self->misc[count] ; count++);
+
+ // Unset value
+ if (!value)
+ {
+ // Remove the keyval, shifting downward
+ for (int i=0,j=0 ; self->misc[i] ; i++, j++)
+ {
+ // If the key is found, remove it
+ if (!strcmp(key, self->misc[i]->key))
+ {
+ px_free(self->misc[i]->key);
+ px_free(self->misc[i]);
+ self->misc[i] = NULL;
+ count--;
+ j--;
+ }
+
+ // Shift down
+ if (i > 0 && j > 0)
+ self->misc[j] = self->misc[i];
+ }
+
+ // Resize array
+ tmp = px_malloc0(sizeof(pxKeyVal *) * (count + 1));
+ memcpy(tmp, self->misc, sizeof(pxKeyVal *) * count);
+ px_free(self->misc);
+ self->misc = tmp;
+ return true;
+ }
+
+ // Attempt to update the value within the array
+ for (int i=0 ; self->misc[i] ; i++)
+ {
+ if (!strcmp(key, self->misc[i]->key))
+ {
+ self->misc[i]->value = (void *) value;
+ return true;
+ }
+ }
+
+ // The key was not found in the array, so add it
+ tmp = px_malloc0(sizeof(pxKeyVal *) * (count + 2));
+ memcpy(tmp, self->misc, sizeof(pxKeyVal *) * count);
+ tmp[count] = px_malloc0(sizeof(pxKeyVal));
+ tmp[count]->key = px_strdup(key);
+ tmp[count]->value = (void *) value;
+ px_free(self->misc);
+ self->misc = tmp;
+ return true;
}
void *
px_proxy_factory_misc_get(pxProxyFactory *self, const char *key)
{
- /* Verify some basic stuff */
+ // Verify some basic stuff
if (!self) return NULL;
if (!key || !strcmp(key, "")) return NULL;
+ if (!self->misc) return NULL;
+
+ // Find the value listed
+ for (int i=0 ; self->misc[i] ; i++)
+ if (!strcmp(key, self->misc[i]->key))
+ return self->misc[i]->value;
- return (void *) px_strdict_get(self->misc, key);
+ return NULL;
}
/**
@@ -446,9 +499,6 @@ px_proxy_factory_misc_get(pxProxyFactory *self, const char *key)
*
* A NULL-terminated array of proxy strings is returned.
* If the first proxy fails, the second should be tried, etc...
- * Don't forget to free the strings/array when you are done.
- * In all cases, at least one entry in the array will be returned.
- * There are no error conditions.
*
* The format of the returned proxy strings are as follows:
* - http://proxy:port
@@ -465,47 +515,48 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
char **response = px_strsplit("direct://", ";");
char *tmp = NULL, *order = NULL, **orderv = NULL;
- /* Verify some basic stuff */
+ // Verify some basic stuff
if (!self) goto do_return;
if (!url || !strcmp(url, "")) goto do_return;
if (!realurl) goto do_return;
- /* Lock mutex */
+ // Lock mutex
pthread_mutex_lock(&self->mutex);
- /* Call the events */
- px_array_foreach(self->on_get_proxies, call_on_proxy_factory_get_proxies, self);
+ // Call the events
+ for (int i=0 ; self->on_get_proxy && self->on_get_proxy[i] ; i++)
+ self->on_get_proxy[i](self);
- /* If our config file is stale, close it */
+ // If our config file is stale, close it
if (self->cf && px_config_file_is_stale(self->cf))
{
px_config_file_free(self->cf);
self->cf = NULL;
}
- /* Try to open our config file if we don't have one */
+ // Try to open our config file if we don't have one
if (!self->cf)
self->cf = px_config_file_new(SYSCONFDIR "/proxy.conf");
- /* If we have a config file, load the order from it */
+ // If we have a config file, load the order from it
if (self->cf)
tmp = px_config_file_get_value(self->cf, PX_CONFIG_FILE_DEFAULT_SECTION, "config_order");
- /* Attempt to get info from the environment */
+ // Attempt to get info from the environment
order = getenv("PX_CONFIG_ORDER");
- /* Create the config order */
+ // Create the config order
order = px_strcat(tmp ? tmp : "", ",", order ? order : "", ",", DEFAULT_CONFIG_ORDER, NULL);
px_free(tmp); tmp = NULL;
- /* Create the config plugin order vector */
+ // Create the config plugin order vector
orderv = px_strsplit(order, ",");
px_free(order);
- /* Get the config by searching the config order */
+ // Get the config by searching the config order
for (int i=0 ; orderv[i] && !config ; i++)
{
- /* Get the category (if applicable) */
+ // Get the category (if applicable)
pxConfigCategory category;
if (!strcmp(orderv[i], "USER"))
category = PX_CONFIG_CATEGORY_USER;
@@ -526,11 +577,11 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
}
px_strfreev(orderv);
- /* No config was found via search order, call all plugins */
+ // No config was found via search order, call all plugins
for (int i=0 ; self->configs && self->configs[i] && !config ; i++)
config = self->configs[i]->callback(self);
- /* No plugin returned a valid config, fall back to 'wpad://' */
+ // No plugin returned a valid config, fall back to 'wpad://'
if (!config)
{
fprintf(stderr, "*** Unable to locate valid config! Falling back to auto-detection...\n");
@@ -539,7 +590,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
config->ignore = px_strdup("");
}
- /* If the config plugin returned an invalid config type or malformed URL, fall back to 'wpad://' */
+ // If the config plugin returned an invalid config type or malformed URL, fall back to 'wpad://'
if (!(!strncmp(config->url, "http://", 7) ||
!strncmp(config->url, "socks://", 8) ||
!strncmp(config->url, "pac+", 4) ||
@@ -564,7 +615,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
config->url = px_strdup("wpad://");
}
- /* Check our ignore patterns */
+ // Check our ignore patterns
char **ignores = px_strsplit(config->ignore, ",");
for (int i=0 ; ignores[i] ; i++)
{
@@ -576,10 +627,10 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
}
px_strfreev(ignores);
- /* If we have a wpad config */
+ // If we have a wpad config
if (!strcmp(config->url, "wpad://"))
{
- /* Get the WPAD object if needed */
+ // Get the WPAD object if needed
if (!self->wpad)
{
if (self->pac) px_pac_free(self->pac);
@@ -592,46 +643,45 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
}
}
- /*
- * If we have no PAC, get one
- * If getting the PAC fails, but the WPAD cycle worked, restart the cycle
- */
+ // If we have no PAC, get one
+ // If getting the PAC fails, but the WPAD cycle worked, restart the cycle
if (!self->pac && !(self->pac = px_wpad_next(self->wpad)) && px_wpad_pac_found(self->wpad))
{
px_wpad_rewind(self->wpad);
self->pac = px_wpad_next(self->wpad);
}
- /* If the WPAD cycle failed, fall back to direct */
+ // If the WPAD cycle failed, fall back to direct
if (!self->pac)
{
fprintf(stderr, "*** Unable to locate PAC! Falling back to direct...\n");
goto do_return;
}
- /* Run the PAC */
+ // Run the PAC
if (self->pac_runner)
{
px_strfreev(response);
response = _format_pac_response(self->pac_runner(self, self->pac, realurl));
}
- /* No PAC runner found, fall back to direct */
+ // No PAC runner found, fall back to direct
else
fprintf(stderr, "*** PAC found, but no active PAC runner! Falling back to direct...\n");
}
- /* If we have a PAC config */
+ // If we have a PAC config
else if (!strncmp(config->url, "pac+", 4))
{
- /* Clear WPAD to indicate that this is a non-WPAD PAC */
+ // Clear WPAD to indicate that this is a non-WPAD PAC
if (self->wpad)
{
px_wpad_free(self->wpad);
self->wpad = NULL;
}
- /* If a PAC already exists, but came from a different URL than the one specified, remove it */
+ // If a PAC alread exists, but comes from a different URL than the one
+ // specified, remove it
if (self->pac)
{
pxURL *urltmp = px_url_new(config->url + 4);
@@ -648,14 +698,14 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
px_url_free(urltmp);
}
- /* Try to load the PAC if it is not already loaded */
+ // Try to load the PAC if it is not already loaded
if (!self->pac && !(self->pac = px_pac_new_from_string(config->url + 4)))
{
fprintf(stderr, "*** Invalid PAC URL! Falling back to direct...\n");
goto do_return;
}
- /* Run the PAC */
+ // Run the PAC
if (self->pac_runner)
{
px_strfreev(response);
@@ -665,7 +715,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
fprintf(stderr, "*** PAC found, but no active PAC runner! Falling back to direct...\n");
}
- /* If we have a manual config (http://..., socks://...) */
+ // If we have a manual config (http://..., socks://...)
else if (!strncmp(config->url, "http://", 7) || !strncmp(config->url, "socks://", 8))
{
if (self->wpad) { px_wpad_free(self->wpad); self->wpad = NULL; }
@@ -674,7 +724,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
response = px_strsplit(config->url, ";");
}
- /* Actually return, freeing misc stuff */
+ // Actually return, freeing misc stuff
do_return:
if (config) { px_free(config->url); px_free(config->ignore); px_free(config); }
if (realurl) px_url_free(realurl);
@@ -683,15 +733,60 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
}
bool
-px_proxy_factory_on_get_proxies_add (pxProxyFactory *self, pxProxyFactoryVoidCallback callback)
+px_proxy_factory_on_get_proxy_add (pxProxyFactory *self, pxProxyFactoryVoidCallback callback)
{
- return self ? px_array_add(self->on_get_proxies, callback) : false;
+ int count;
+ pxProxyFactoryVoidCallback *tmp;
+
+ // Verify some basic stuff
+ if (!self) return false;
+ if (!callback) return false;
+
+ // Allocate an empty config array if there is none
+ if (!self->on_get_proxy) self->on_get_proxy = px_malloc0(sizeof(pxProxyFactoryVoidCallback));
+
+ // Get a count of how many callbacks we have
+ for (count=0 ; self->on_get_proxy[count] ; count++);
+
+ // Allocate new array, copy old values into it and free old array
+ tmp = px_malloc0(sizeof(pxProxyFactoryVoidCallback) * (count + 2));
+ memcpy(tmp, self->on_get_proxy, sizeof(pxProxyFactoryVoidCallback) * count);
+ px_free(self->on_get_proxy);
+ self->on_get_proxy = tmp;
+
+ // Add the new callback to the end
+ self->on_get_proxy[count] = callback;
+
+ return true;
}
bool
-px_proxy_factory_on_get_proxies_del (pxProxyFactory *self, pxProxyFactoryVoidCallback callback)
+px_proxy_factory_on_get_proxy_del (pxProxyFactory *self, pxProxyFactoryVoidCallback callback)
{
- return self ? px_array_del(self->on_get_proxies, callback) : false;
+ int i,j;
+
+ // Verify some basic stuff
+ if (!self) return false;
+ if (!callback) return false;
+ if (!self->on_get_proxy) return false;
+
+ // Remove and shift all callbacks down (if found)
+ for (i=0,j=0 ; self->on_get_proxy[j]; i++,j++)
+ {
+ if (i != j)
+ self->on_get_proxy[j] = self->on_get_proxy[i];
+ else if (self->on_get_proxy[i] == callback)
+ self->on_get_proxy[j--] = NULL;
+ }
+
+ // If we have an empty array, free it
+ if (!self->on_get_proxy[0])
+ {
+ px_free(self->on_get_proxy);
+ self->on_get_proxy = NULL;
+ }
+
+ return i != j ? true : false;
}
bool
@@ -706,10 +801,17 @@ px_proxy_factory_pac_runner_set (pxProxyFactory *self, pxPACRunnerCallback callb
void
px_proxy_factory_network_changed(pxProxyFactory *self)
{
- px_wpad_free(self->wpad);
- px_pac_free(self->pac);
- self->wpad = NULL;
- self->pac = NULL;
+ if (self->wpad)
+ {
+ px_wpad_free(self->wpad);
+ self->wpad = NULL;
+ }
+
+ if (self->pac)
+ {
+ px_pac_free(self->pac);
+ self->pac = NULL;
+ }
}
/**
@@ -718,18 +820,42 @@ px_proxy_factory_network_changed(pxProxyFactory *self)
void
px_proxy_factory_free (pxProxyFactory *self)
{
+ unsigned int i;
+
if (!self) return;
pthread_mutex_lock(&self->mutex);
- /* Free the plugins */
- px_array_foreach(self->plugins, destantiate_plugins, self);
- px_array_free(self->plugins);
+ // Free the plugins
+ if (self->plugins)
+ {
+ for (i=0 ; self->plugins[i] ; i++)
+ {
+ // Call the destantiation hook
+ pxProxyFactoryVoidCallback destantiate;
+ destantiate = dlsym(self->plugins[i], "on_proxy_factory_destantiate");
+ if (destantiate)
+ destantiate(self);
+
+ // Unload the plugin
+ dlclose(self->plugins[i]);
+ self->plugins[i] = NULL;
+ }
+ px_free(self->plugins);
+ }
- /* Free misc */
- px_strdict_free(self->misc);
+ // Free misc
+ if (self->misc)
+ {
+ for (i=0 ; self->misc[i] ; i++)
+ {
+ px_free(self->misc[i]->key);
+ px_free(self->misc[i]);
+ }
+ px_free(self->misc);
+ }
- /* Free everything else */
+ // Free everything else
px_pac_free(self->pac);
px_wpad_free(self->wpad);
px_config_file_free(self->cf);