From f0f9c5d24a0a261367371fd420bc3a3e04b5285f Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Tue, 20 Sep 2016 15:00:17 -0300 Subject: [PATCH] libproxy: dlopen() and make it runtime optional. --- configure.ac | 13 --- src/lib/ecore_con/ecore_con.c | 132 +++++++++++++++++------- src/lib/ecore_con/ecore_con_private.h | 10 +- src/lib/ecore_con/efl_net_dialer_http.c | 16 +-- 4 files changed, 101 insertions(+), 70 deletions(-) diff --git a/configure.ac b/configure.ac index a403484603..d0b9962823 100644 --- a/configure.ac +++ b/configure.ac @@ -224,7 +224,6 @@ case "$host_os" in ;; freebsd*) have_freebsd="yes" - want_libproxy="yes" ELM_UNIX_DEF="#define" ;; darwin*) @@ -235,7 +234,6 @@ case "$host_os" in have_linux="yes" have_systemd_pkg="auto" want_systemd="yes" - want_libproxy="yes" ELM_UNIX_DEF="#define" ;; *) @@ -3034,16 +3032,6 @@ EFL_LIB_START([Ecore_Con]) ### Default values -AC_ARG_ENABLE([libproxy], - [AS_HELP_STRING([--enable-libproxy],[Enable libproxy support. @<:@default=enabled@:>@])], - [ - if test "x${enableval}" = "xyes" ; then - want_libproxy="yes" - else - want_libproxy="no" - fi - ]) - want_ecore_con_local_sockets="yes" want_ecore_con_abstract_sockets="yes" @@ -3080,7 +3068,6 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_CON], [emile]) EFL_ADD_LIBS([ECORE_CON], [-lm]) EFL_OPTIONAL_DEPEND_PKG([ECORE_CON], [${want_systemd}], [SYSTEMD], [libsystemd]) -EFL_OPTIONAL_DEPEND_PKG([ECORE_CON], [${want_libproxy}], [LIBPROXY], [libproxy-1.0]) EFL_ADD_FEATURE([ECORE_CON], [local-sockets], [${want_ecore_con_local_sockets}]) EFL_ADD_FEATURE([ECORE_CON], [abstract-sockets], [${want_ecore_con_abstract_sockets}]) diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c index d79c77ec30..cc17fe8348 100644 --- a/src/lib/ecore_con/ecore_con.c +++ b/src/lib/ecore_con/ecore_con.c @@ -191,9 +191,15 @@ int _ecore_con_log_dom = -1; Ecore_Con_Socks *_ecore_con_proxy_once = NULL; Ecore_Con_Socks *_ecore_con_proxy_global = NULL; -#ifdef HAVE_LIBPROXY -pxProxyFactory *_ecore_con_libproxy_factory = NULL; -#endif +typedef struct pxProxyFactory_ pxProxyFactory; +typedef struct _Ecore_Con_Libproxy { + pxProxyFactory *factory; + char **(*px_proxy_factory_get_proxies)(pxProxyFactory *factory, const char *url); + void *(*px_proxy_factory_new)(void); + void (*px_proxy_factory_free)(pxProxyFactory *); + Eina_Module *mod; +} Ecore_Con_Libproxy; +static Ecore_Con_Libproxy _ecore_con_libproxy; EAPI int ecore_con_init(void) @@ -279,13 +285,16 @@ ecore_con_shutdown(void) if (--_ecore_con_init_count != 0) return _ecore_con_init_count; -#ifdef HAVE_LIBPROXY - if (_ecore_con_libproxy_factory) + if (_ecore_con_libproxy.factory) { - px_proxy_factory_free(_ecore_con_libproxy_factory); - _ecore_con_libproxy_factory = NULL; + _ecore_con_libproxy.px_proxy_factory_free(_ecore_con_libproxy.factory); + _ecore_con_libproxy.factory = NULL; + } + if (_ecore_con_libproxy.mod) + { + eina_module_free(_ecore_con_libproxy.mod); + _ecore_con_libproxy.mod = NULL; } -#endif eina_log_timing(_ecore_con_log_dom, EINA_LOG_STATE_START, @@ -4444,32 +4453,15 @@ _efl_net_ip_connect_async_run_socks5h(Efl_Net_Ip_Connect_Async_Data *d, const ch EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */ } -#ifdef HAVE_LIBPROXY -static void -_cleanup_proxies(void *data) -{ - char **proxies = data; - char **itr; - - if (!proxies) return; - - for (itr = proxies; *itr != NULL; itr++) - free(*itr); - free(proxies); -} -#endif - static void _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) { Efl_Net_Ip_Connect_Async_Data *d = data; const char *host, *port, *proxy; char *addrcopy; -#ifdef HAVE_LIBPROXY char **proxies = NULL; int proxies_idx = 0; Eina_Bool is_libproxy = EINA_FALSE; -#endif addrcopy = strdup(d->address); if (!addrcopy) @@ -4489,8 +4481,7 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) proxy = d->proxy; -#ifdef HAVE_LIBPROXY - if ((!proxy) && (_ecore_con_libproxy_factory)) + if ((!proxy) && (_ecore_con_libproxy.factory)) { /* libproxy is thread-safe but not cancellable. the provided * parameter must be a URL with schema, otherwise it won't @@ -4499,11 +4490,11 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) char *url; asprintf(&url, "%s://%s:%s", d->protocol == IPPROTO_UDP ? "udp" : "tcp", host, port); - proxies = px_proxy_factory_get_proxies(_ecore_con_libproxy_factory, url); + proxies = ecore_con_libproxy_proxies_get(url); free(url); } - EINA_THREAD_CLEANUP_PUSH(_cleanup_proxies, proxies); + EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)ecore_con_libproxy_proxies_free, proxies); next_proxy: if ((!proxy) && (proxies) && (proxies_idx >= 0)) { @@ -4529,7 +4520,6 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) proxies_idx++; } } -#endif if (!proxy) { @@ -4581,14 +4571,12 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) } else { -#ifdef HAVE_LIBPROXY if (is_libproxy) { DBG("libproxy said %s but it's not supported, try next proxy", proxy); proxy = NULL; goto next_proxy; } -#endif /* maybe bogus envvar, ignore it */ WRN("proxy protocol not supported '%s', connect directly", proxy); _efl_net_ip_connect_async_run_direct(d, host, port); @@ -4597,23 +4585,19 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) if ((d->error) && (!d->proxy) && (proxy[0] != '\0')) { -#ifdef HAVE_LIBPROXY if (is_libproxy) { DBG("libproxy said %s but it failed, try next proxy", proxy); proxy = NULL; goto next_proxy; } -#endif WRN("error using proxy '%s' from environment, try direct connect", proxy); _efl_net_ip_connect_async_run_direct(d, host, port); } eina_thread_cancellable_set(EINA_FALSE, NULL); -#ifdef HAVE_LIBPROXY EINA_THREAD_CLEANUP_POP(EINA_TRUE); -#endif EINA_THREAD_CLEANUP_POP(EINA_TRUE); } @@ -4714,10 +4698,6 @@ efl_net_ip_connect_async_new(const char *address, const char *proxy, const char d->sockfd = -1; d->error = 0; -#ifdef HAVE_LIBPROXY - if (!_ecore_con_libproxy_factory) - _ecore_con_libproxy_factory = px_proxy_factory_new(); -#endif return ecore_thread_run(_efl_net_ip_connect_async_run, _efl_net_ip_connect_async_end, @@ -4734,3 +4714,75 @@ efl_net_ip_connect_async_new(const char *address, const char *proxy, const char free(d); return NULL; } + +Eina_Bool +ecore_con_libproxy_init(void) +{ + if (!_ecore_con_libproxy.mod) + { +#define LOAD(x) \ + if (!_ecore_con_libproxy.mod) { \ + _ecore_con_libproxy.mod = eina_module_new(x); \ + if (_ecore_con_libproxy.mod) { \ + if (!eina_module_load(_ecore_con_libproxy.mod)) { \ + eina_module_free(_ecore_con_libproxy.mod); \ + _ecore_con_libproxy.mod = NULL; \ + } \ + } \ + } +#if defined(_WIN32) || defined(__CYGWIN__) + LOAD("libproxy-1.dll"); + LOAD("libproxy.dll"); +#elif defined(__APPLE__) && defined(__MACH__) + LOAD("libproxy.1.dylib"); + LOAD("libproxy.dylib"); +#else + LOAD("libproxy.so.1"); + LOAD("libproxy.so"); +#endif +#undef LOAD + if (!_ecore_con_libproxy.mod) + { + DBG("Couldn't find libproxy in your system. Continue without it"); + return EINA_FALSE; + } + +#define SYM(x) \ + if ((_ecore_con_libproxy.x = eina_module_symbol_get(_ecore_con_libproxy.mod, #x)) == NULL) { \ + ERR("libproxy (%s) missing symbol %s", eina_module_file_get(_ecore_con_libproxy.mod), #x); \ + eina_module_free(_ecore_con_libproxy.mod); \ + _ecore_con_libproxy.mod = NULL; \ + return EINA_FALSE; \ + } + + SYM(px_proxy_factory_new); + SYM(px_proxy_factory_free); + SYM(px_proxy_factory_get_proxies); +#undef SYM + DBG("using libproxy=%s", eina_module_file_get(_ecore_con_libproxy.mod)); + } + + if (!_ecore_con_libproxy.factory) + _ecore_con_libproxy.factory = _ecore_con_libproxy.px_proxy_factory_new(); + + return !!_ecore_con_libproxy.factory; +} + +char ** +ecore_con_libproxy_proxies_get(const char *url) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_con_libproxy.px_proxy_factory_get_proxies, NULL); + return _ecore_con_libproxy.px_proxy_factory_get_proxies(_ecore_con_libproxy.factory, url); +} + +void +ecore_con_libproxy_proxies_free(char **proxies) +{ + char **itr; + + if (!proxies) return; + + for (itr = proxies; *itr != NULL; itr++) + free(*itr); + free(proxies); +} diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h index 82e2d44b2b..f85433b3dc 100644 --- a/src/lib/ecore_con/ecore_con_private.h +++ b/src/lib/ecore_con/ecore_con_private.h @@ -254,10 +254,12 @@ extern int sd_fd_index; extern int sd_fd_max; #endif -#ifdef HAVE_LIBPROXY -# include -extern pxProxyFactory *_ecore_con_libproxy_factory; -#endif +/* init must be called from main thread */ +Eina_Bool ecore_con_libproxy_init(void); +void ecore_con_libproxy_proxies_free(char **proxies); +/* BLOCKING! should be called from a worker thread */ +char **ecore_con_libproxy_proxies_get(const char *url); + extern Ecore_Con_Socks *_ecore_con_proxy_once; extern Ecore_Con_Socks *_ecore_con_proxy_global; diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index 1b5b20bfc9..9e16d8ad40 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -181,9 +181,7 @@ typedef struct Eina_Stringshare *address_remote; Eina_Stringshare *method; Eina_Stringshare *user_agent; -#ifdef HAVE_LIBPROXY Ecore_Thread *libproxy_thread; -#endif struct { struct curl_slist *headers; int64_t content_length; @@ -1169,13 +1167,12 @@ _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) EOLIAN static void _efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) { -#ifdef HAVE_LIBPROXY if (pd->libproxy_thread) { ecore_thread_cancel(pd->libproxy_thread); pd->libproxy_thread = NULL; } -#endif + if (pd->in_curl_callback) { DBG("deleting HTTP dialer=%p from CURL callback.", o); @@ -1263,7 +1260,6 @@ _efl_net_dialer_http_curl_start(Eo *o, Efl_Net_Dialer_Http_Data *pd) DBG("started curl request easy=%p, cm=%p", pd->easy, pd->cm); } -#ifdef HAVE_LIBPROXY typedef struct _Efl_Net_Dialer_Http_Libproxy_Context { Eo *o; char *url; @@ -1274,7 +1270,7 @@ static void _efl_net_dialer_http_libproxy_run(void *data, Ecore_Thread *thread EINA_UNUSED) { Efl_Net_Dialer_Http_Libproxy_Context *ctx = data; - char **proxies = px_proxy_factory_get_proxies(_ecore_con_libproxy_factory, ctx->url); + char **proxies = ecore_con_libproxy_proxies_get(ctx->url); char **itr; if (!proxies) return; @@ -1332,7 +1328,6 @@ _efl_net_dialer_http_libproxy_cancel(void *data, Ecore_Thread *thread EINA_UNUSE Efl_Net_Dialer_Http_Libproxy_Context *ctx = data; _efl_net_dialer_http_libproxy_context_free(ctx); } -#endif EOLIAN static Eina_Error _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, const char *address) @@ -1357,14 +1352,10 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co return EINVAL; } -#ifdef HAVE_LIBPROXY - if (!pd->proxy) + if ((!pd->proxy) && (ecore_con_libproxy_init())) { Efl_Net_Dialer_Http_Libproxy_Context *ctx; - if (!_ecore_con_libproxy_factory) - _ecore_con_libproxy_factory = px_proxy_factory_new(); - if (pd->libproxy_thread) ecore_thread_cancel(pd->libproxy_thread); @@ -1394,7 +1385,6 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co free(ctx); return ENOMEM; } -#endif _efl_net_dialer_http_curl_start(o, pd);