diff --git a/.gitignore b/.gitignore index 0dbb55242c..b00829a17d 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ Session.vim /elm_intro.h /src/modules/evas/engines/gl_common/shader_3d/evas_3d_shaders.x /src/scripts/eo/eo_debug +/src/bin/ecore_con/efl_net_proxy_helper diff --git a/src/Makefile_Ecore_Con.am b/src/Makefile_Ecore_Con.am index 3c62337d2f..093c26a183 100644 --- a/src/Makefile_Ecore_Con.am +++ b/src/Makefile_Ecore_Con.am @@ -80,6 +80,7 @@ nodist_installed_ecoreconmainheaders_DATA = \ lib_ecore_con_libecore_con_la_SOURCES = \ lib/ecore_con/ecore_con_alloc.c \ lib/ecore_con/ecore_con.c \ +lib/ecore_con/ecore_con_proxy_helper.c \ lib/ecore_con/ecore_con_legacy.c \ lib/ecore_con/ecore_con_eet.c \ lib/ecore_con/ecore_con_socks.c \ @@ -152,7 +153,12 @@ lib/ecore_con/efl_net_dialer_unix.c \ lib/ecore_con/efl_net_server_unix.c endif -lib_ecore_con_libecore_con_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_CON_CFLAGS@ +lib_ecore_con_libecore_con_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/ecore\" \ +-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \ +@ECORE_CON_CFLAGS@ lib_ecore_con_libecore_con_la_LIBADD = @ECORE_CON_LIBS@ @EVIL_LIBS@ lib_ecore_con_libecore_con_la_DEPENDENCIES = @ECORE_CON_INTERNAL_LIBS@ lib_ecore_con_libecore_con_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ @@ -169,6 +175,22 @@ static_libs/http-parser/test.c \ static_libs/http-parser/contrib/parsertrace.c \ static_libs/http-parser/contrib/url_parser.c +### Binary +proxyhelperdir = \ +$(libdir)/ecore_con/utils/$(MODULE_ARCH) +proxyhelper_PROGRAMS = bin/ecore_con/efl_net_proxy_helper + +bin_ecore_con_efl_net_proxy_helper_SOURCES = \ +bin/ecore_con/efl_net_proxy_helper.c + +bin_ecore_con_efl_net_proxy_helper_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ +-DPACKAGE_BIN_DIR=\"$(bindir)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +-DPACKAGE_DATA_DIR=\"$(datadir)/ecore\" \ +@EINA_CFLAGS@ +bin_ecore_con_efl_net_proxy_helper_LDADD = @USE_EINA_LIBS@ +bin_ecore_con_efl_net_proxy_helper_DEPEDNENCIES = @USE_EINA_INTERNAL_LIBS@ + ### Unit tests if EFL_ENABLE_TESTS diff --git a/src/bin/ecore_con/efl_net_proxy_helper.c b/src/bin/ecore_con/efl_net_proxy_helper.c new file mode 100644 index 0000000000..69c371a12f --- /dev/null +++ b/src/bin/ecore_con/efl_net_proxy_helper.c @@ -0,0 +1,264 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "Eina.h" + +#ifdef ERR +# undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(EINA_LOG_DOMAIN_GLOBAL, __VA_ARGS__) + +#ifdef DBG +# undef DBG +#endif +#define DBG(...) EINA_LOG_DOM_DBG(EINA_LOG_DOMAIN_GLOBAL, __VA_ARGS__) + +#ifdef INF +# undef INF +#endif +#define INF(...) EINA_LOG_DOM_INFO(EINA_LOG_DOMAIN_GLOBAL, __VA_ARGS__) + +#ifdef WRN +# undef WRN +#endif +#define WRN(...) EINA_LOG_DOM_WARN(EINA_LOG_DOMAIN_GLOBAL, __VA_ARGS__) + +#ifdef CRI +# undef CRI +#endif +#define CRI(...) EINA_LOG_DOM_CRIT(EINA_LOG_DOMAIN_GLOBAL, __VA_ARGS__) + +typedef struct pxProxyFactory_ pxProxyFactory; +typedef struct _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; +} Libproxy; +static Libproxy _libproxy = { 0 }; + +static Eina_Spinlock pending_lock; +static int pending = 0; +static int opcount = 0; +static Eina_List *join_list = NULL; + +static Eina_Bool +init(void) +{ + if (!_libproxy.mod) + { +#define LOAD(x) \ + if (!_libproxy.mod) { \ + _libproxy.mod = eina_module_new(x); \ + if (_libproxy.mod) { \ + if (!eina_module_load(_libproxy.mod)) { \ + eina_module_free(_libproxy.mod); \ + _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 (!_libproxy.mod) + { + DBG("Couldn't find libproxy in your system. Continue without it"); + return EINA_FALSE; + } + +#define SYM(x) \ + if ((_libproxy.x = eina_module_symbol_get(_libproxy.mod, #x)) == NULL) { \ + ERR("libproxy (%s) missing symbol %s", \ + eina_module_file_get(_libproxy.mod), #x); \ + eina_module_free(_libproxy.mod); \ + _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(_libproxy.mod)); + } + + if (!_libproxy.factory) + _libproxy.factory = _libproxy.px_proxy_factory_new(); + + return !!_libproxy.factory; +} + +static void +shutdown(void) +{ + if (_libproxy.factory) + { + _libproxy.px_proxy_factory_free(_libproxy.factory); + _libproxy.factory = NULL; + } + if (_libproxy.mod) + { + eina_module_free(_libproxy.mod); + _libproxy.mod = NULL; + } +} + +static void * +proxy_lookup(void *data, Eina_Thread t) +{ + char *cmd = data; + char **proxies, **itr; + const char *p, *url; + int id = atoi(cmd + 2); + int pending_local, opcount_prev; + + if (id > 0) + { + for (p = cmd + 2; *p && (*p != ' '); p++); + if (*p == ' ') + { + url = p + 1; + proxies = _libproxy.px_proxy_factory_get_proxies + (_libproxy.factory, url); + if (proxies) + { + for (itr = proxies; *itr != NULL; itr++) + { + fprintf(stdout, "P %i P %s\n", id, *itr); + free(*itr); + } + free(proxies); + } + fprintf(stdout, "P %i E\n", id); + fflush(stdout); + } + } + free(cmd); + + eina_spinlock_take(&pending_lock); + { + pending--; + pending_local = pending; + opcount_prev = opcount; + } + eina_spinlock_release(&pending_lock); + // if there are no more pending threads doing work - sleep for the + // timeout then check if we still are and if so - exit; + if (pending_local == 0) sleep(10); + eina_spinlock_take(&pending_lock); + { + Eina_Thread *tt; + + if ((pending == 0) & (opcount == opcount_prev)) exit(0); + tt = calloc(1, sizeof(Eina_Thread)); + if (tt) + { + *tt = t; + join_list = eina_list_append(join_list, tt); + } + } + eina_spinlock_release(&pending_lock); + return NULL; +} + +static void +handle(const char *cmd) +{ + // "P 1234 URL" -> Get Proxy, id=1234, url=URL + if ((cmd[0] == 'P') && (cmd[1] == ' ')) + { + char *dup = strdup(cmd); + + if (dup) + { + Eina_Thread t; + + eina_spinlock_take(&pending_lock); + { + pending++; + opcount++; + } + eina_spinlock_release(&pending_lock); + if (!eina_thread_create(&t, EINA_THREAD_BACKGROUND, -1, + proxy_lookup, dup)) + { + abort(); + } + } + return; + } +} + +static void +clean_threads(void) +{ + eina_spinlock_take(&pending_lock); + { + Eina_Thread *t; + + EINA_LIST_FREE(join_list, t) + { + eina_thread_join(*t); + free(t); + } + } + eina_spinlock_release(&pending_lock); +} + +int +main(int argc EINA_UNUSED, char **argv EINA_UNUSED) +{ + char inbuf[8192]; + eina_init(); + if (init()) + { + eina_spinlock_new(&pending_lock); + // 1 command per stdin line + while (fgets(inbuf, sizeof(inbuf) - 1, stdin)) + { + // strip off newline and ensure the string is 0 terminated + int len = strlen(inbuf); + if (len > 0) + { + if (inbuf[len -1 ] == '\n') inbuf[len - 1] = 0; + else inbuf[len] = 0; + handle(inbuf); + } + clean_threads(); + } + eina_spinlock_free(&pending_lock); + shutdown(); + } + else + { + // Failed to init libproxy so report this before exit + fprintf(stdout, "F\n"); + fflush(stdout); + pause(); + } + eina_shutdown(); + return 0; +} diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c index 58e0805955..dd641da479 100644 --- a/src/lib/ecore_con/ecore_con.c +++ b/src/lib/ecore_con/ecore_con.c @@ -68,15 +68,11 @@ EWAPI Eina_Error EFL_NET_SOCKET_SSL_ERROR_CERTIFICATE_VERIFY_FAILED = 0; static int _ecore_con_init_count = 0; int _ecore_con_log_dom = -1; -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; +Eina_Bool _efl_net_proxy_helper_can_do (void); +int _efl_net_proxy_helper_url_req_send(const char *url); +char **_efl_net_proxy_helper_url_wait (int id); +void _efl_net_proxy_helper_init (void); +void _efl_net_proxy_helper_shutdown (void); EAPI int ecore_con_init(void) @@ -100,6 +96,8 @@ ecore_con_init(void) goto ecore_con_log_error; } + _efl_net_proxy_helper_init(); + ecore_con_mempool_init(); ecore_con_legacy_init(); @@ -145,16 +143,7 @@ ecore_con_shutdown(void) if (--_ecore_con_init_count != 0) return _ecore_con_init_count; - if (_ecore_con_libproxy.factory) - { - _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; - } + _efl_net_proxy_helper_shutdown(); eina_log_timing(_ecore_con_log_dom, EINA_LOG_STATE_START, @@ -2079,12 +2068,8 @@ _efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) proxy = d->proxy; - if ((!proxy) && (_ecore_con_libproxy.factory)) + if ((!proxy) && _efl_net_proxy_helper_can_do()) { - /* libproxy is thread-safe but not cancellable. the provided - * parameter must be a URL with schema, otherwise it won't - * return anything. - */ Eina_Stringshare *url; url = eina_stringshare_printf("%s://%s:%s", d->protocol == IPPROTO_UDP ? "udp" : "tcp", host, port); @@ -2608,64 +2593,12 @@ efl_net_udp_datagram_size_query(SOCKET fd) return READBUFSIZ; } -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); + int id = _efl_net_proxy_helper_url_req_send(url); + if (id < 0) return NULL; + return _efl_net_proxy_helper_url_wait(id); } void diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h index bcc9deacfe..42f6dedef7 100644 --- a/src/lib/ecore_con/ecore_con_private.h +++ b/src/lib/ecore_con/ecore_con_private.h @@ -93,7 +93,6 @@ extern int sd_fd_max; #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); diff --git a/src/lib/ecore_con/ecore_con_proxy_helper.c b/src/lib/ecore_con/ecore_con_proxy_helper.c new file mode 100644 index 0000000000..eda91e9989 --- /dev/null +++ b/src/lib/ecore_con/ecore_con_proxy_helper.c @@ -0,0 +1,427 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "Ecore.h" +#include "ecore_private.h" +#include "Ecore_Con.h" +#include "ecore_con_private.h" + +typedef struct { + Eina_Thread_Queue *thq; + char *str; + char **proxies; + int id; + int busy; +} Efl_Net_Proxy_Helper_Req; + +typedef struct { + Eina_Thread_Queue_Msg head; + char **proxies; +} Efl_Net_Proxy_Helper_Thq_Msg; + +static Eina_Bool _efl_net_proxy_helper_works = EINA_TRUE; +static Ecore_Exe *_efl_net_proxy_helper_exe = NULL; +static Eina_Prefix *_efl_net_proxy_helper_prefix = NULL; +static Eina_Spinlock _efl_net_proxy_helper_queue_lock; +static int _efl_net_proxy_helper_req_id = 0; +static Eina_List *_efl_net_proxy_helper_queue = NULL; +static Ecore_Event_Handler *_efl_net_proxy_helper_handler_exe_del = NULL; +static Ecore_Event_Handler *_efl_net_proxy_helper_handler_exe_data = NULL; +static Eina_Bool _efl_net_proxy_helper_queue_lock_init = EINA_FALSE; +static int _efl_net_proxy_helper_init_num = 0; + +static int locks = 0; + +#ifdef _WIN32 +# define HELPER_EXT ".exe" +#else +# define HELPER_EXT +#endif + +static void +_efl_net_proxy_helper_spawn(void) +{ + char buf[PATH_MAX]; + Eina_List *l; + Efl_Net_Proxy_Helper_Req *req; + static int run_in_tree = -1; + + if (!_efl_net_proxy_helper_works) return; + if (_efl_net_proxy_helper_exe) return; + if (run_in_tree == -1) + { + run_in_tree = 0; +#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) + if (getuid() == geteuid()) +#endif + { + if (getenv("EFL_RUN_IN_TREE")) run_in_tree = 1; + } + } + // find binary location path + if (run_in_tree == 1) + snprintf + (buf, sizeof(buf), + PACKAGE_BUILD_DIR"/src/bin/ecore_con/utils/efl_net_proxy_helper"HELPER_EXT); + else + snprintf + (buf, sizeof(buf), + "%s/ecore_con/utils/"MODULE_ARCH"/efl_net_proxy_helper"HELPER_EXT, + eina_prefix_lib_get(_efl_net_proxy_helper_prefix)); + // run it with stdin/out piped line buffered with events + _efl_net_proxy_helper_exe = ecore_exe_pipe_run + (buf, + ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE | + ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_TERM_WITH_PARENT | + ECORE_EXE_NOT_LEADER, NULL); + // resend unhandled requests + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + EINA_LIST_FOREACH(_efl_net_proxy_helper_queue, l, req) + ecore_exe_send(_efl_net_proxy_helper_exe, + req->str, strlen(req->str)); + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); +} + +static void +_efl_net_proxy_helper_kill(void) +{ + if (!_efl_net_proxy_helper_exe) return; + // don't exit if anything is pending + if (_efl_net_proxy_helper_queue) return; + ecore_exe_kill(_efl_net_proxy_helper_exe); + ecore_exe_free(_efl_net_proxy_helper_exe); + _efl_net_proxy_helper_exe = NULL; +} + +static void +_efl_net_proxy_helper_cancel(void) +{ + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + Efl_Net_Proxy_Helper_Req *req; + + EINA_LIST_FREE(_efl_net_proxy_helper_queue, req) + { + Efl_Net_Proxy_Helper_Thq_Msg *msg; + void *ref; + + msg = eina_thread_queue_send + (req->thq, sizeof(Efl_Net_Proxy_Helper_Thq_Msg), &ref); + msg->proxies = NULL; + eina_thread_queue_send_done(req->thq, ref); + if (!req->busy) + { + free(req->str); + ecore_con_libproxy_proxies_free(req->proxies); + eina_thread_queue_free(req->thq); + free(req); + } + } + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); +} + +static void +_efl_net_proxy_helper_proxy_add(int id, const char *url) +{ + Eina_List *l; + Efl_Net_Proxy_Helper_Req *req; + + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + EINA_LIST_FOREACH(_efl_net_proxy_helper_queue, l, req) + { + if (req->id == id) break; + req = NULL; + } + if (req) + { + if (url) + { + char **proxies = req->proxies; + int n = 0; + + if (proxies) + { + for (n = 0; proxies[n]; n++); + } + n++; + proxies = realloc(proxies, sizeof(char *) * (n + 1)); + if (proxies) + { + req->proxies = proxies; + proxies[n - 1] = strdup(url); + proxies[n] = NULL; + } + } + else + { + Efl_Net_Proxy_Helper_Thq_Msg *msg; + void *ref; + + msg = eina_thread_queue_send + (req->thq, sizeof(Efl_Net_Proxy_Helper_Thq_Msg), &ref); + msg->proxies = req->proxies; + req->proxies = NULL; + eina_thread_queue_send_done(req->thq, ref); + } + } + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); +} + +static Eina_Bool +_efl_net_proxy_helper_cb_exe_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *info) +{ + Ecore_Exe_Event_Del *event = info; + + if (!_efl_net_proxy_helper_exe) return EINA_TRUE; + if (event->exe == _efl_net_proxy_helper_exe) + { + static double last_respawn = 0.0; + double t; + Eina_Bool respawn = EINA_FALSE; + + t = ecore_time_get(); + _efl_net_proxy_helper_exe = NULL; + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + if (_efl_net_proxy_helper_queue) + { + if ((t - last_respawn) > 5.0) respawn = EINA_TRUE; + } + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + if (respawn) + { + last_respawn = t; + _efl_net_proxy_helper_spawn(); + } + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_efl_net_proxy_helper_cb_exe_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *info) +{ + Ecore_Exe_Event_Data *event = info; + + if (!_efl_net_proxy_helper_exe) return EINA_TRUE; + if (event->exe == _efl_net_proxy_helper_exe) + { + if (event->lines) + { + int i; + + for (i = 0; event->lines[i].line; i++) + { + char *line = event->lines[i].line; + + if (line[0] == 'F') // failure + { + _efl_net_proxy_helper_works = EINA_FALSE; + _efl_net_proxy_helper_cancel(); + _efl_net_proxy_helper_kill(); + } + else if ((line[0] == 'P') && (line[1] == ' ')) // proxy + { + int id = atoi(line + 2); + char *p, *url = NULL; + + for (p = line + 2; *p && (*p != ' '); p++); + if ((p[0] == ' ') && (p[1] == 'P') && (p[2] == ' ')) + url = p + 3; + else if ((p[0] == ' ') && (p[1] == 'E')) + url = NULL; + _efl_net_proxy_helper_proxy_add(id, url); + } + } + } + return EINA_FALSE; + } + return EINA_TRUE; +} + +Eina_Bool +_efl_net_proxy_helper_can_do(void) +{ + return _efl_net_proxy_helper_works; +} + + +static void +_efl_net_proxy_helper_cb_send_do(void *data) +{ + char *str = data; + if (!str) return; + // spawn exe if needed + if (!_efl_net_proxy_helper_exe) _efl_net_proxy_helper_spawn(); + if (_efl_net_proxy_helper_exe) + ecore_exe_send(_efl_net_proxy_helper_exe, str, strlen(str)); + free(str); +} + +int +_efl_net_proxy_helper_url_req_send(const char *url) +{ + char *buf; + int id = -1; + Efl_Net_Proxy_Helper_Req *req; + + if (!_efl_net_proxy_helper_works) return -1; + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + // new id - just an int that eventually loops. + _efl_net_proxy_helper_req_id++; + if (_efl_net_proxy_helper_req_id >= ((1 << 30) - 1)) + _efl_net_proxy_helper_req_id = 1; + id = _efl_net_proxy_helper_req_id; + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + // create request to quque up to look up responses for + req = calloc(1, sizeof(Efl_Net_Proxy_Helper_Req)); + if (!req) return -1; + req->id = id; + req->thq = eina_thread_queue_new(); + if (!req->thq) + { + free(req); + return -1; + } + buf = alloca(strlen(url) + 256); + sprintf(buf, "P %i %s\n", req->id, url); + req->str = strdup(buf); + if (!req->str) + { + eina_thread_queue_free(req->thq); + free(req); + return -1; + } + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + _efl_net_proxy_helper_queue = + eina_list_append(_efl_net_proxy_helper_queue, req); + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + // actually send the req now i'ts queued + ecore_main_loop_thread_safe_call_async + (_efl_net_proxy_helper_cb_send_do, strdup(buf)); + return id; +} + +char ** +_efl_net_proxy_helper_url_wait(int id) +{ + Eina_List *l; + Efl_Net_Proxy_Helper_Req *req; + Efl_Net_Proxy_Helper_Thq_Msg *msg; + void *ref; + char **ret = NULL; + + if (id < 0) return NULL; + if (!_efl_net_proxy_helper_exe) return NULL; + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + EINA_LIST_FOREACH(_efl_net_proxy_helper_queue, l, req) + { + if (req->id == id) break; + req = NULL; + } + if (!req) goto end; + req->busy++; + locks--; + } + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + + msg = eina_thread_queue_wait(req->thq, &ref); + ret = msg->proxies; + msg->proxies = NULL; + eina_thread_queue_wait_done(req->thq, ref); + + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + { + locks++; + free(req->str); + ecore_con_libproxy_proxies_free(req->proxies); + eina_thread_queue_free(req->thq); + _efl_net_proxy_helper_queue = + eina_list_remove(_efl_net_proxy_helper_queue, req); + free(req); + } +end: + locks--; + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + return ret; +} + +void +_efl_net_proxy_helper_init(void) +{ + _efl_net_proxy_helper_init_num++; + if (_efl_net_proxy_helper_init_num > 1) return; + if (_efl_net_proxy_helper_prefix) return; + _efl_net_proxy_helper_prefix = eina_prefix_new + (NULL, ecore_con_init, "ECORE", "ecore", "checkme", + PACKAGE_BIN_DIR, PACKAGE_LIB_DIR, PACKAGE_DATA_DIR, PACKAGE_DATA_DIR); + if (!_efl_net_proxy_helper_queue_lock_init) + { + eina_spinlock_new(&_efl_net_proxy_helper_queue_lock); + _efl_net_proxy_helper_queue_lock_init = EINA_TRUE; + } + _efl_net_proxy_helper_handler_exe_del = + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _efl_net_proxy_helper_cb_exe_del, NULL); + _efl_net_proxy_helper_handler_exe_data = + ecore_event_handler_add(ECORE_EXE_EVENT_DATA, + _efl_net_proxy_helper_cb_exe_data, NULL); +} + +void +_efl_net_proxy_helper_shutdown(void) +{ + _efl_net_proxy_helper_init_num--; + if (_efl_net_proxy_helper_init_num > 0) return; + if (!_efl_net_proxy_helper_prefix) return; + if (_efl_net_proxy_helper_exe) + { + _efl_net_proxy_helper_cancel(); + _efl_net_proxy_helper_kill(); + } + eina_spinlock_take(&_efl_net_proxy_helper_queue_lock); + eina_spinlock_release(&_efl_net_proxy_helper_queue_lock); + eina_prefix_free(_efl_net_proxy_helper_prefix); + _efl_net_proxy_helper_prefix = NULL; + ecore_event_handler_del(_efl_net_proxy_helper_handler_exe_del); + _efl_net_proxy_helper_handler_exe_del = NULL; + ecore_event_handler_del(_efl_net_proxy_helper_handler_exe_data); + _efl_net_proxy_helper_handler_exe_data = NULL; +} diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index b4d39e456e..b5fe3e461f 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -1380,7 +1380,7 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co #undef IS_HEADER } - if ((!pd->proxy) && (ecore_con_libproxy_init())) + if (!pd->proxy) { Efl_Net_Dialer_Http_Libproxy_Context *ctx;