2017-01-08 05:57:54 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2017-09-22 03:06:10 -07:00
|
|
|
#ifdef _WIN32
|
2017-01-08 05:57:54 -08:00
|
|
|
# include <Evil.h>
|
|
|
|
#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;
|
2017-11-07 05:41:20 -08:00
|
|
|
int fails;
|
2017-01-08 05:57:54 -08:00
|
|
|
} 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
|
|
|
|
|
2017-12-17 19:25:59 -08:00
|
|
|
static void
|
|
|
|
_efl_net_proxy_helper_delete_cb(void *data EINA_UNUSED, const Efl_Event *ev)
|
|
|
|
{
|
|
|
|
if (ev->object == _efl_net_proxy_helper_exe)
|
|
|
|
{
|
|
|
|
INF("HTTP proxy helper object died before the process exited.");
|
|
|
|
_efl_net_proxy_helper_exe = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-08 05:57:54 -08:00
|
|
|
static void
|
|
|
|
_efl_net_proxy_helper_spawn(void)
|
|
|
|
{
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
Eina_List *l;
|
|
|
|
Efl_Net_Proxy_Helper_Req *req;
|
2017-02-03 05:49:38 -08:00
|
|
|
#ifdef NEED_RUN_IN_TREE
|
2017-01-08 05:57:54 -08:00
|
|
|
static int run_in_tree = -1;
|
2017-02-03 05:49:38 -08:00
|
|
|
#endif
|
2017-01-08 05:57:54 -08:00
|
|
|
|
|
|
|
if (!_efl_net_proxy_helper_works) return;
|
|
|
|
if (_efl_net_proxy_helper_exe) return;
|
2017-02-03 05:49:38 -08:00
|
|
|
#ifdef NEED_RUN_IN_TREE
|
2017-01-08 05:57:54 -08:00
|
|
|
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
|
2017-02-03 05:49:38 -08:00
|
|
|
#endif
|
2017-01-08 05:57:54 -08:00
|
|
|
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);
|
2017-12-17 19:25:59 -08:00
|
|
|
efl_event_callback_add(_efl_net_proxy_helper_exe, EFL_EVENT_DEL,
|
|
|
|
_efl_net_proxy_helper_delete_cb, NULL);
|
2017-01-08 05:57:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2017-07-24 01:35:13 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("Out of memory allocating proxies in helper");
|
|
|
|
goto err;
|
|
|
|
}
|
2017-01-08 05:57:54 -08:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2017-07-24 01:35:13 -07:00
|
|
|
err:
|
2017-01-08 05:57:54 -08:00
|
|
|
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;
|
2017-11-07 05:41:20 -08:00
|
|
|
int min_fails = 0;
|
2017-01-08 05:57:54 -08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2017-11-07 05:41:20 -08:00
|
|
|
if (respawn)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Efl_Net_Proxy_Helper_Req *req;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(_efl_net_proxy_helper_queue, l, req)
|
|
|
|
{
|
|
|
|
req->fails++;
|
|
|
|
if (req->fails > min_fails) min_fails = req->fails;
|
|
|
|
}
|
|
|
|
}
|
2017-01-08 05:57:54 -08:00
|
|
|
locks--;
|
|
|
|
}
|
|
|
|
eina_spinlock_release(&_efl_net_proxy_helper_queue_lock);
|
2017-11-07 05:41:20 -08:00
|
|
|
if (min_fails >= 5) _efl_net_proxy_helper_cancel();
|
|
|
|
else if (respawn)
|
2017-01-08 05:57:54 -08:00
|
|
|
{
|
|
|
|
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);
|
2017-02-07 18:33:42 -08:00
|
|
|
if (!msg) return NULL;
|
2017-01-08 05:57:54 -08:00
|
|
|
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;
|
|
|
|
}
|