diff options
author | Gustavo Sverzut Barbieri <barbieri@profusion.mobi> | 2016-09-19 10:00:36 -0300 |
---|---|---|
committer | Gustavo Sverzut Barbieri <barbieri@profusion.mobi> | 2016-09-19 10:01:51 -0300 |
commit | 8550a33b27b35065b4f5bd6defbece003e1af0de (patch) | |
tree | 76bc6e75ad86a1f01cd27e5f7d3d6a75773ffb70 | |
parent | 0d478c301f49fccfd94a107c060696f79490c30d (diff) | |
download | efl-8550a33b27b35065b4f5bd6defbece003e1af0de.tar.gz |
efl_net_dialer_http: use libproxy.
query libproxy in a thread (since it's nasty and blocks), then apply
proxy to curl and execute the request.
-rw-r--r-- | src/lib/ecore_con/efl_net_dialer_http.c | 146 |
1 files changed, 137 insertions, 9 deletions
diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index 1e7fd549c0..1b5b20bfc9 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -181,6 +181,9 @@ 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; @@ -1166,6 +1169,13 @@ _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); @@ -1234,10 +1244,99 @@ _efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) _secure_free(&pd->authentication.password); } +static void +_efl_net_dialer_http_curl_start(Eo *o, Efl_Net_Dialer_Http_Data *pd) +{ + Efl_Net_Dialer_Http_Curlm *cm; + + // TODO: move this to be per-loop once multiple mainloops are supported + // this would need to attach something to the loop + cm = &_cm_global; + if (!cm->loop) cm->loop = efl_loop_user_loop_get(o); + if (!_efl_net_dialer_http_curlm_add(cm, o, pd->easy)) + { + ERR("dialer=%p could not add curl easy handle to multi manager", o); + return; + } + + pd->cm = cm; + 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; + char *proxy; +} Efl_Net_Dialer_Http_Libproxy_Context; + +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 **itr; + + if (!proxies) return; + + for (itr = proxies; *itr != NULL; itr++) + { + if (itr != proxies) free(*itr); + else + { + if (strcmp(*itr, "direct://") != 0) ctx->proxy = *itr; + else + { + /* NULL not "" so we let curl use envvars */ + ctx->proxy = NULL; + free(*itr); + } + } + } + free(proxies); +} + +static void +_efl_net_dialer_http_libproxy_context_free(Efl_Net_Dialer_Http_Libproxy_Context *ctx) +{ + free(ctx->proxy); + free(ctx->url); + free(ctx); +} + +static void +_efl_net_dialer_http_libproxy_end(void *data, Ecore_Thread *thread EINA_UNUSED) +{ + Efl_Net_Dialer_Http_Libproxy_Context *ctx = data; + Eo *o = ctx->o; + Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS); + + if (ctx->proxy) + { + CURLcode r = curl_easy_setopt(pd->easy, CURLOPT_PROXY, ctx->proxy); + if (r != CURLE_OK) + ERR("dialer=%p could not set proxy to '%s': %s", + o, ctx->proxy, curl_easy_strerror(r)); + else + DBG("libproxy said %s for %s", ctx->proxy, pd->address_dial); + } + + _efl_net_dialer_http_libproxy_context_free(ctx); + + _efl_net_dialer_http_curl_start(o, pd); +} + +static void +_efl_net_dialer_http_libproxy_cancel(void *data, Ecore_Thread *thread EINA_UNUSED) +{ + 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) { - Efl_Net_Dialer_Http_Curlm *cm; CURLcode r; EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL); @@ -1258,17 +1357,46 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co return EINVAL; } - // TODO: move this to be per-loop once multiple mainloops are supported - // this would need to attach something to the loop - cm = &_cm_global; - if (!cm->loop) cm->loop = efl_loop_user_loop_get(o); - if (!_efl_net_dialer_http_curlm_add(cm, o, pd->easy)) +#ifdef HAVE_LIBPROXY + if (!pd->proxy) { - ERR("dialer=%p could not add curl easy handle to multi manager", o); - return ENOSYS; + 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); + + ctx = calloc(1, sizeof(Efl_Net_Dialer_Http_Libproxy_Context)); + EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, ENOMEM); + + if (strstr(address, "://")) ctx->url = strdup(address); + else + { + ctx->url = malloc(strlen("http://") + strlen(address) + 1); + if (ctx->url) + { + memcpy(ctx->url, "http://", strlen("http://")); + memcpy(ctx->url + strlen("http://"), address, strlen(address) + 1); + } + } + EINA_SAFETY_ON_NULL_GOTO(ctx->url, url_error); + + ctx->o = o; + + pd->libproxy_thread = ecore_thread_run(_efl_net_dialer_http_libproxy_run, + _efl_net_dialer_http_libproxy_end, + _efl_net_dialer_http_libproxy_cancel, + ctx); + return 0; + url_error: + free(ctx); + return ENOMEM; } +#endif - pd->cm = cm; + _efl_net_dialer_http_curl_start(o, pd); DBG("HTTP dialer=%p, curl_easy=%p, address='%s'", o, pd->easy, pd->address_dial); |