From 16a9961f58e94c9893479ceb50c250b2507a7b27 Mon Sep 17 00:00:00 2001 From: Bluezery Date: Wed, 21 Dec 2011 06:18:25 +0000 Subject: [PATCH] From: Bluezery Subject: Re: [E-devel] [Patch][ecore_con_url] Add proxy & timeout set API There existed two problems when using ecore_con_url. We cannot set proxy and set timeout. So, I added two APIs for solving these problems. Proxy can be set by setting libcurl option. Timeout also can be set but It need to add handler for Linux alarm signal. (Please refer: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTTIMEOUT) So I implemented it by using ecore timer. SVN revision: 66414 --- legacy/ecore/ChangeLog | 3 + legacy/ecore/NEWS | 2 + legacy/ecore/src/lib/ecore_con/Ecore_Con.h | 33 +++++++ .../src/lib/ecore_con/ecore_con_private.h | 2 + .../ecore/src/lib/ecore_con/ecore_con_url.c | 85 ++++++++++++++++++- .../src/lib/ecore_file/ecore_file_download.c | 2 + 6 files changed, 126 insertions(+), 1 deletion(-) diff --git a/legacy/ecore/ChangeLog b/legacy/ecore/ChangeLog index a8a0a1aa3a..4d770059f7 100644 --- a/legacy/ecore/ChangeLog +++ b/legacy/ecore/ChangeLog @@ -430,3 +430,6 @@ * Add XIM attribute support to Ecore_IMF +2011-12-21 Tae-Hwan Kim (Bluezery) + + * Add proxy set and timeout set functions in ecore_con. diff --git a/legacy/ecore/NEWS b/legacy/ecore/NEWS index 1da17aff45..ae24d72dfe 100644 --- a/legacy/ecore/NEWS +++ b/legacy/ecore/NEWS @@ -11,6 +11,8 @@ Additions: - ecore_con_ssl_server_verify_name_set/get - ecore_con_ssl_server_cafile_add() now accepts directories - ECORE_CON_REMOTE_CORK + - ecore_con_url_proxy_set() + - ecore_con_url_timeout_set() * ecore_x: - ecore_x_randr_output_backlight_available() diff --git a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h index d6df0cedb0..cd39f085b0 100644 --- a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h +++ b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h @@ -1844,6 +1844,39 @@ EAPI void ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con, EAPI int ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path); +/** + * Set HTTP proxy to use. + * + * The parameter should be a char * to a zero terminated string holding + * the host name or dotted IP address. To specify port number in this string, + * append :[port] to the end of the host name. + * The proxy string may be prefixed with [protocol]:// since any such prefix + * will be ignored. + * The proxy's port number may optionally be specified with the separate option. + * If not specified, libcurl will default to using port 1080 for proxies. + * + * @param url_con Connection object that will use the proxy. + * @param proxy Porxy string or @c NULL to disable + * + * @return #EINA_TRUE on success, #EINA_FALSE on error. + * @since 1.2 + */ +EAPI Eina_Bool ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy); + +/** + * Set timeout in seconds. + * + * the maximum time in seconds that you allow the ecore con url transfer + * operation to take. Normally, name lookups can take a considerable time + * and limiting operations to less than a few minutes risk aborting perfectly + * normal operations. + * + * @param url_con Connection object that will use the timeout. + * @param timeout time in seconds. + * @since 1.2 + */ +EAPI void ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout); + /** * @} */ diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h index 2aef9027b9..098c520df0 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h @@ -204,6 +204,8 @@ struct _Ecore_Con_Url Eina_List *response_headers; const char *url; + Ecore_Timer *timer; + Ecore_Con_Url_Time time_condition; double timestamp; void *data; diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_url.c b/legacy/ecore/src/lib/ecore_con/ecore_con_url.c index cf6c2162fc..ea6dd4c8e5 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_url.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_url.c @@ -57,6 +57,7 @@ static void _ecore_con_event_url_free(void *data __UNUSED__, void *ev); static Eina_Bool _ecore_con_url_idler_handler(void *data); static Eina_Bool _ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__); +static Eina_Bool _ecore_con_url_timeout_cb(void *data); static Eina_List *_url_con_list = NULL; static Eina_List *_fd_hd_list = NULL; @@ -294,12 +295,13 @@ ecore_con_url_free(Ecore_Con_Url *url_con) { ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret)); + _url_con_list = eina_list_remove(_url_con_list, url_con); } curl_easy_cleanup(url_con->curl_easy); } + if (url_con->timer) ecore_timer_del(url_con->timer); - _url_con_list = eina_list_remove(_url_con_list, url_con); curl_slist_free_all(url_con->headers); EINA_LIST_FREE(url_con->additional_headers, s) free(s); @@ -1067,12 +1069,93 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path) return res; } +EAPI Eina_Bool +ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy) +{ +#ifdef HAVE_CURL + int res = -1; + if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) + { + ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_set"); + return EINA_FALSE; + } + + if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; + if (!url_con->url) return EINA_FALSE; + + if (proxy == NULL) res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, ""); + else res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, proxy); + + if (res != CURLE_OK) + { + ERR("curl_easy_setopt() failed"); + return EINA_FALSE; + } + return EINA_TRUE; +#else + return EINA_FALSE; + (void)url_con; + (void)proxy; +#endif + return res; +} + +EAPI void +ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout) +{ +#ifdef HAVE_CURL + if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) + { + ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_timeout_set"); + return; + } + + if (eina_list_data_find(_url_con_list, url_con)) return; + if (!url_con->url || timeout < 0) return; + if (url_con->timer) ecore_timer_del(url_con->timer); + url_con->timer = ecore_timer_add(timeout, _ecore_con_url_timeout_cb, url_con); +#else + return; + (void)url_con; + (void)timeout; +#endif +} /** * @} */ #ifdef HAVE_CURL +static Eina_Bool +_ecore_con_url_timeout_cb(void *data) +{ + Ecore_Con_Url *url_con = data; + CURLMcode ret; + Ecore_Con_Event_Url_Complete *e; + + if (!url_con) return ECORE_CALLBACK_CANCEL; + if (!url_con->curl_easy) return ECORE_CALLBACK_CANCEL; + if (!eina_list_data_find(_url_con_list, url_con)) return ECORE_CALLBACK_CANCEL; + + ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); + if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret)); + _url_con_list = eina_list_remove(_url_con_list, url_con); + + curl_slist_free_all(url_con->headers); + url_con->headers = NULL; + + url_con->timer = NULL; + + e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); + if (e) + { + e->url_con = url_con; + e->status = 0; + ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, _ecore_con_event_url_free, NULL); + } + return ECORE_CALLBACK_CANCEL; +} + static size_t _ecore_con_url_data_cb(void *buffer, size_t size, diff --git a/legacy/ecore/src/lib/ecore_file/ecore_file_download.c b/legacy/ecore/src/lib/ecore_file/ecore_file_download.c index 38855ad019..c5e56bd8bd 100644 --- a/legacy/ecore/src/lib/ecore_file/ecore_file_download.c +++ b/legacy/ecore/src/lib/ecore_file/ecore_file_download.c @@ -15,6 +15,7 @@ #ifdef BUILD_ECORE_CON #define ECORE_MAGIC_FILE_DOWNLOAD_JOB 0xf7427cb8 +#define ECORE_FILE_DOWNLOAD_TIMEOUT 30 struct _Ecore_File_Download_Job { @@ -361,6 +362,7 @@ _ecore_file_download_curl(const char *url, const char *dst, } if (headers) eina_hash_foreach(headers, _ecore_file_download_headers_foreach_cb, job); + ecore_con_url_timeout_set(job->url_con, ECORE_FILE_DOWNLOAD_TIMEOUT); ecore_con_url_fd_set(job->url_con, fileno(job->file)); ecore_con_url_data_set(job->url_con, data);