summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-09-20 15:00:17 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-09-20 15:00:48 -0300
commitf0f9c5d24a0a261367371fd420bc3a3e04b5285f (patch)
treec7ea93c07b56ade65c764d7d85ba389fa980904f /src
parent132ae9683c242b695d1bb3050c09f83386d0667d (diff)
libproxy: dlopen() and make it runtime optional.
Diffstat (limited to 'src')
-rw-r--r--src/lib/ecore_con/ecore_con.c132
-rw-r--r--src/lib/ecore_con/ecore_con_private.h10
-rw-r--r--src/lib/ecore_con/efl_net_dialer_http.c16
3 files changed, 101 insertions, 57 deletions
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;
191Ecore_Con_Socks *_ecore_con_proxy_once = NULL; 191Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
192Ecore_Con_Socks *_ecore_con_proxy_global = NULL; 192Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
193 193
194#ifdef HAVE_LIBPROXY 194typedef struct pxProxyFactory_ pxProxyFactory;
195pxProxyFactory *_ecore_con_libproxy_factory = NULL; 195typedef struct _Ecore_Con_Libproxy {
196#endif 196 pxProxyFactory *factory;
197 char **(*px_proxy_factory_get_proxies)(pxProxyFactory *factory, const char *url);
198 void *(*px_proxy_factory_new)(void);
199 void (*px_proxy_factory_free)(pxProxyFactory *);
200 Eina_Module *mod;
201} Ecore_Con_Libproxy;
202static Ecore_Con_Libproxy _ecore_con_libproxy;
197 203
198EAPI int 204EAPI int
199ecore_con_init(void) 205ecore_con_init(void)
@@ -279,13 +285,16 @@ ecore_con_shutdown(void)
279 if (--_ecore_con_init_count != 0) 285 if (--_ecore_con_init_count != 0)
280 return _ecore_con_init_count; 286 return _ecore_con_init_count;
281 287
282#ifdef HAVE_LIBPROXY 288 if (_ecore_con_libproxy.factory)
283 if (_ecore_con_libproxy_factory)
284 { 289 {
285 px_proxy_factory_free(_ecore_con_libproxy_factory); 290 _ecore_con_libproxy.px_proxy_factory_free(_ecore_con_libproxy.factory);
286 _ecore_con_libproxy_factory = NULL; 291 _ecore_con_libproxy.factory = NULL;
292 }
293 if (_ecore_con_libproxy.mod)
294 {
295 eina_module_free(_ecore_con_libproxy.mod);
296 _ecore_con_libproxy.mod = NULL;
287 } 297 }
288#endif
289 298
290 eina_log_timing(_ecore_con_log_dom, 299 eina_log_timing(_ecore_con_log_dom,
291 EINA_LOG_STATE_START, 300 EINA_LOG_STATE_START,
@@ -4444,32 +4453,15 @@ _efl_net_ip_connect_async_run_socks5h(Efl_Net_Ip_Connect_Async_Data *d, const ch
4444 EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */ 4453 EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */
4445} 4454}
4446 4455
4447#ifdef HAVE_LIBPROXY
4448static void
4449_cleanup_proxies(void *data)
4450{
4451 char **proxies = data;
4452 char **itr;
4453
4454 if (!proxies) return;
4455
4456 for (itr = proxies; *itr != NULL; itr++)
4457 free(*itr);
4458 free(proxies);
4459}
4460#endif
4461
4462static void 4456static void
4463_efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) 4457_efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
4464{ 4458{
4465 Efl_Net_Ip_Connect_Async_Data *d = data; 4459 Efl_Net_Ip_Connect_Async_Data *d = data;
4466 const char *host, *port, *proxy; 4460 const char *host, *port, *proxy;
4467 char *addrcopy; 4461 char *addrcopy;
4468#ifdef HAVE_LIBPROXY
4469 char **proxies = NULL; 4462 char **proxies = NULL;
4470 int proxies_idx = 0; 4463 int proxies_idx = 0;
4471 Eina_Bool is_libproxy = EINA_FALSE; 4464 Eina_Bool is_libproxy = EINA_FALSE;
4472#endif
4473 4465
4474 addrcopy = strdup(d->address); 4466 addrcopy = strdup(d->address);
4475 if (!addrcopy) 4467 if (!addrcopy)
@@ -4489,8 +4481,7 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
4489 4481
4490 proxy = d->proxy; 4482 proxy = d->proxy;
4491 4483
4492#ifdef HAVE_LIBPROXY 4484 if ((!proxy) && (_ecore_con_libproxy.factory))
4493 if ((!proxy) && (_ecore_con_libproxy_factory))
4494 { 4485 {
4495 /* libproxy is thread-safe but not cancellable. the provided 4486 /* libproxy is thread-safe but not cancellable. the provided
4496 * parameter must be a URL with schema, otherwise it won't 4487 * 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)
4499 char *url; 4490 char *url;
4500 4491
4501 asprintf(&url, "%s://%s:%s", d->protocol == IPPROTO_UDP ? "udp" : "tcp", host, port); 4492 asprintf(&url, "%s://%s:%s", d->protocol == IPPROTO_UDP ? "udp" : "tcp", host, port);
4502 proxies = px_proxy_factory_get_proxies(_ecore_con_libproxy_factory, url); 4493 proxies = ecore_con_libproxy_proxies_get(url);
4503 free(url); 4494 free(url);
4504 } 4495 }
4505 4496
4506 EINA_THREAD_CLEANUP_PUSH(_cleanup_proxies, proxies); 4497 EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)ecore_con_libproxy_proxies_free, proxies);
4507 next_proxy: 4498 next_proxy:
4508 if ((!proxy) && (proxies) && (proxies_idx >= 0)) 4499 if ((!proxy) && (proxies) && (proxies_idx >= 0))
4509 { 4500 {
@@ -4529,7 +4520,6 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
4529 proxies_idx++; 4520 proxies_idx++;
4530 } 4521 }
4531 } 4522 }
4532#endif
4533 4523
4534 if (!proxy) 4524 if (!proxy)
4535 { 4525 {
@@ -4581,14 +4571,12 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
4581 } 4571 }
4582 else 4572 else
4583 { 4573 {
4584#ifdef HAVE_LIBPROXY
4585 if (is_libproxy) 4574 if (is_libproxy)
4586 { 4575 {
4587 DBG("libproxy said %s but it's not supported, try next proxy", proxy); 4576 DBG("libproxy said %s but it's not supported, try next proxy", proxy);
4588 proxy = NULL; 4577 proxy = NULL;
4589 goto next_proxy; 4578 goto next_proxy;
4590 } 4579 }
4591#endif
4592 /* maybe bogus envvar, ignore it */ 4580 /* maybe bogus envvar, ignore it */
4593 WRN("proxy protocol not supported '%s', connect directly", proxy); 4581 WRN("proxy protocol not supported '%s', connect directly", proxy);
4594 _efl_net_ip_connect_async_run_direct(d, host, port); 4582 _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)
4597 4585
4598 if ((d->error) && (!d->proxy) && (proxy[0] != '\0')) 4586 if ((d->error) && (!d->proxy) && (proxy[0] != '\0'))
4599 { 4587 {
4600#ifdef HAVE_LIBPROXY
4601 if (is_libproxy) 4588 if (is_libproxy)
4602 { 4589 {
4603 DBG("libproxy said %s but it failed, try next proxy", proxy); 4590 DBG("libproxy said %s but it failed, try next proxy", proxy);
4604 proxy = NULL; 4591 proxy = NULL;
4605 goto next_proxy; 4592 goto next_proxy;
4606 } 4593 }
4607#endif
4608 4594
4609 WRN("error using proxy '%s' from environment, try direct connect", proxy); 4595 WRN("error using proxy '%s' from environment, try direct connect", proxy);
4610 _efl_net_ip_connect_async_run_direct(d, host, port); 4596 _efl_net_ip_connect_async_run_direct(d, host, port);
4611 } 4597 }
4612 4598
4613 eina_thread_cancellable_set(EINA_FALSE, NULL); 4599 eina_thread_cancellable_set(EINA_FALSE, NULL);
4614#ifdef HAVE_LIBPROXY
4615 EINA_THREAD_CLEANUP_POP(EINA_TRUE); 4600 EINA_THREAD_CLEANUP_POP(EINA_TRUE);
4616#endif
4617 EINA_THREAD_CLEANUP_POP(EINA_TRUE); 4601 EINA_THREAD_CLEANUP_POP(EINA_TRUE);
4618} 4602}
4619 4603
@@ -4714,10 +4698,6 @@ efl_net_ip_connect_async_new(const char *address, const char *proxy, const char
4714 d->sockfd = -1; 4698 d->sockfd = -1;
4715 d->error = 0; 4699 d->error = 0;
4716 4700
4717#ifdef HAVE_LIBPROXY
4718 if (!_ecore_con_libproxy_factory)
4719 _ecore_con_libproxy_factory = px_proxy_factory_new();
4720#endif
4721 4701
4722 return ecore_thread_run(_efl_net_ip_connect_async_run, 4702 return ecore_thread_run(_efl_net_ip_connect_async_run,
4723 _efl_net_ip_connect_async_end, 4703 _efl_net_ip_connect_async_end,
@@ -4734,3 +4714,75 @@ efl_net_ip_connect_async_new(const char *address, const char *proxy, const char
4734 free(d); 4714 free(d);
4735 return NULL; 4715 return NULL;
4736} 4716}
4717
4718Eina_Bool
4719ecore_con_libproxy_init(void)
4720{
4721 if (!_ecore_con_libproxy.mod)
4722 {
4723#define LOAD(x) \
4724 if (!_ecore_con_libproxy.mod) { \
4725 _ecore_con_libproxy.mod = eina_module_new(x); \
4726 if (_ecore_con_libproxy.mod) { \
4727 if (!eina_module_load(_ecore_con_libproxy.mod)) { \
4728 eina_module_free(_ecore_con_libproxy.mod); \
4729 _ecore_con_libproxy.mod = NULL; \
4730 } \
4731 } \
4732 }
4733#if defined(_WIN32) || defined(__CYGWIN__)
4734 LOAD("libproxy-1.dll");
4735 LOAD("libproxy.dll");
4736#elif defined(__APPLE__) && defined(__MACH__)
4737 LOAD("libproxy.1.dylib");
4738 LOAD("libproxy.dylib");
4739#else
4740 LOAD("libproxy.so.1");
4741 LOAD("libproxy.so");
4742#endif
4743#undef LOAD
4744 if (!_ecore_con_libproxy.mod)
4745 {
4746 DBG("Couldn't find libproxy in your system. Continue without it");
4747 return EINA_FALSE;
4748 }
4749
4750#define SYM(x) \
4751 if ((_ecore_con_libproxy.x = eina_module_symbol_get(_ecore_con_libproxy.mod, #x)) == NULL) { \
4752 ERR("libproxy (%s) missing symbol %s", eina_module_file_get(_ecore_con_libproxy.mod), #x); \
4753 eina_module_free(_ecore_con_libproxy.mod); \
4754 _ecore_con_libproxy.mod = NULL; \
4755 return EINA_FALSE; \
4756 }
4757
4758 SYM(px_proxy_factory_new);
4759 SYM(px_proxy_factory_free);
4760 SYM(px_proxy_factory_get_proxies);
4761#undef SYM
4762 DBG("using libproxy=%s", eina_module_file_get(_ecore_con_libproxy.mod));
4763 }
4764
4765 if (!_ecore_con_libproxy.factory)
4766 _ecore_con_libproxy.factory = _ecore_con_libproxy.px_proxy_factory_new();
4767
4768 return !!_ecore_con_libproxy.factory;
4769}
4770
4771char **
4772ecore_con_libproxy_proxies_get(const char *url)
4773{
4774 EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_con_libproxy.px_proxy_factory_get_proxies, NULL);
4775 return _ecore_con_libproxy.px_proxy_factory_get_proxies(_ecore_con_libproxy.factory, url);
4776}
4777
4778void
4779ecore_con_libproxy_proxies_free(char **proxies)
4780{
4781 char **itr;
4782
4783 if (!proxies) return;
4784
4785 for (itr = proxies; *itr != NULL; itr++)
4786 free(*itr);
4787 free(proxies);
4788}
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;
254extern int sd_fd_max; 254extern int sd_fd_max;
255#endif 255#endif
256 256
257#ifdef HAVE_LIBPROXY 257/* init must be called from main thread */
258# include <proxy.h> 258Eina_Bool ecore_con_libproxy_init(void);
259extern pxProxyFactory *_ecore_con_libproxy_factory; 259void ecore_con_libproxy_proxies_free(char **proxies);
260#endif 260/* BLOCKING! should be called from a worker thread */
261char **ecore_con_libproxy_proxies_get(const char *url);
262
261 263
262extern Ecore_Con_Socks *_ecore_con_proxy_once; 264extern Ecore_Con_Socks *_ecore_con_proxy_once;
263extern Ecore_Con_Socks *_ecore_con_proxy_global; 265extern 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
181 Eina_Stringshare *address_remote; 181 Eina_Stringshare *address_remote;
182 Eina_Stringshare *method; 182 Eina_Stringshare *method;
183 Eina_Stringshare *user_agent; 183 Eina_Stringshare *user_agent;
184#ifdef HAVE_LIBPROXY
185 Ecore_Thread *libproxy_thread; 184 Ecore_Thread *libproxy_thread;
186#endif
187 struct { 185 struct {
188 struct curl_slist *headers; 186 struct curl_slist *headers;
189 int64_t content_length; 187 int64_t content_length;
@@ -1169,13 +1167,12 @@ _efl_net_dialer_http_efl_object_constructor(Eo *o, Efl_Net_Dialer_Http_Data *pd)
1169EOLIAN static void 1167EOLIAN static void
1170_efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) 1168_efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd)
1171{ 1169{
1172#ifdef HAVE_LIBPROXY
1173 if (pd->libproxy_thread) 1170 if (pd->libproxy_thread)
1174 { 1171 {
1175 ecore_thread_cancel(pd->libproxy_thread); 1172 ecore_thread_cancel(pd->libproxy_thread);
1176 pd->libproxy_thread = NULL; 1173 pd->libproxy_thread = NULL;
1177 } 1174 }
1178#endif 1175
1179 if (pd->in_curl_callback) 1176 if (pd->in_curl_callback)
1180 { 1177 {
1181 DBG("deleting HTTP dialer=%p from CURL callback.", o); 1178 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)
1263 DBG("started curl request easy=%p, cm=%p", pd->easy, pd->cm); 1260 DBG("started curl request easy=%p, cm=%p", pd->easy, pd->cm);
1264} 1261}
1265 1262
1266#ifdef HAVE_LIBPROXY
1267typedef struct _Efl_Net_Dialer_Http_Libproxy_Context { 1263typedef struct _Efl_Net_Dialer_Http_Libproxy_Context {
1268 Eo *o; 1264 Eo *o;
1269 char *url; 1265 char *url;
@@ -1274,7 +1270,7 @@ static void
1274_efl_net_dialer_http_libproxy_run(void *data, Ecore_Thread *thread EINA_UNUSED) 1270_efl_net_dialer_http_libproxy_run(void *data, Ecore_Thread *thread EINA_UNUSED)
1275{ 1271{
1276 Efl_Net_Dialer_Http_Libproxy_Context *ctx = data; 1272 Efl_Net_Dialer_Http_Libproxy_Context *ctx = data;
1277 char **proxies = px_proxy_factory_get_proxies(_ecore_con_libproxy_factory, ctx->url); 1273 char **proxies = ecore_con_libproxy_proxies_get(ctx->url);
1278 char **itr; 1274 char **itr;
1279 1275
1280 if (!proxies) return; 1276 if (!proxies) return;
@@ -1332,7 +1328,6 @@ _efl_net_dialer_http_libproxy_cancel(void *data, Ecore_Thread *thread EINA_UNUSE
1332 Efl_Net_Dialer_Http_Libproxy_Context *ctx = data; 1328 Efl_Net_Dialer_Http_Libproxy_Context *ctx = data;
1333 _efl_net_dialer_http_libproxy_context_free(ctx); 1329 _efl_net_dialer_http_libproxy_context_free(ctx);
1334} 1330}
1335#endif
1336 1331
1337EOLIAN static Eina_Error 1332EOLIAN static Eina_Error
1338_efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, const char *address) 1333_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
1357 return EINVAL; 1352 return EINVAL;
1358 } 1353 }
1359 1354
1360#ifdef HAVE_LIBPROXY 1355 if ((!pd->proxy) && (ecore_con_libproxy_init()))
1361 if (!pd->proxy)
1362 { 1356 {
1363 Efl_Net_Dialer_Http_Libproxy_Context *ctx; 1357 Efl_Net_Dialer_Http_Libproxy_Context *ctx;
1364 1358
1365 if (!_ecore_con_libproxy_factory)
1366 _ecore_con_libproxy_factory = px_proxy_factory_new();
1367
1368 if (pd->libproxy_thread) 1359 if (pd->libproxy_thread)
1369 ecore_thread_cancel(pd->libproxy_thread); 1360 ecore_thread_cancel(pd->libproxy_thread);
1370 1361
@@ -1394,7 +1385,6 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co
1394 free(ctx); 1385 free(ctx);
1395 return ENOMEM; 1386 return ENOMEM;
1396 } 1387 }
1397#endif
1398 1388
1399 _efl_net_dialer_http_curl_start(o, pd); 1389 _efl_net_dialer_http_curl_start(o, pd);
1400 1390