summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-09-19 10:00:36 -0300
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-09-19 10:01:51 -0300
commit8550a33b27b35065b4f5bd6defbece003e1af0de (patch)
tree76bc6e75ad86a1f01cd27e5f7d3d6a75773ffb70
parent0d478c301f49fccfd94a107c060696f79490c30d (diff)
downloadefl-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.c146
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);