diff --git a/legacy/ecore/configure.in b/legacy/ecore/configure.in index c983ea4b0e..6895c3990d 100644 --- a/legacy/ecore/configure.in +++ b/legacy/ecore/configure.in @@ -100,7 +100,6 @@ if test "x$want_curl" = "xyes"; then PKG_CHECK_MODULES(CURL, libcurl, [ AC_DEFINE(HAVE_CURL, 1, [ Downloading with CURL ]) - requirements_ecore_file="$requirements_ecore_file libcurl" requirements_ecore_con="$requirements_ecore_con libcurl" have_curl="yes" ], @@ -721,6 +720,7 @@ if test "x$have_ecore_file" = "xyes"; then AC_DEFINE(HAVE_POLL, 1, [ File monitoring with polling ]) have_poll="yes" fi + requirements_ecore_file="$requirements_ecore_file $requirements_ecore_con" fi dnl ecore_desktop diff --git a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h index 01375f4299..e977c846b9 100644 --- a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h +++ b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h @@ -149,8 +149,14 @@ extern "C" { struct _Ecore_Con_Event_Url_Progress { Ecore_Con_Url *url_con; - double total; - double now; + struct { + double total; + double now; + } down; + struct { + double total; + double now; + } up; }; EAPI extern int ECORE_CON_EVENT_CLIENT_ADD; @@ -161,8 +167,7 @@ extern "C" { EAPI extern int ECORE_CON_EVENT_SERVER_DATA; EAPI extern int ECORE_CON_EVENT_URL_DATA; EAPI extern int ECORE_CON_EVENT_URL_COMPLETE; - EAPI extern int ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD; - EAPI extern int ECORE_CON_EVENT_URL_PROGRESS_UPLOAD; + EAPI extern int ECORE_CON_EVENT_URL_PROGRESS; EAPI int ecore_con_init(void); EAPI int ecore_con_shutdown(void); @@ -196,6 +201,8 @@ extern "C" { EAPI void ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data); EAPI void *ecore_con_url_data_get(Ecore_Con_Url *url_con); EAPI int ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url); + EAPI void ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd); + EAPI int ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con); EAPI int ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *content_type); EAPI void ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t tm); 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 820771a0a1..d5d9258d43 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h @@ -78,6 +78,11 @@ struct _Ecore_Con_Url void *data; Ecore_Fd_Handler *fd_handler; + int fd; + int flags; + + int received; + int write_fd; unsigned char active : 1; }; 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 5b673068de..97077cece8 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_url.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_url.c @@ -40,6 +40,8 @@ #include "Ecore_Con.h" #include "ecore_con_private.h" +#include + /** * @defgroup Ecore_Con_Url_Group Ecore URL Connection Functions * @@ -50,8 +52,7 @@ int ECORE_CON_EVENT_URL_DATA = 0; int ECORE_CON_EVENT_URL_COMPLETE = 0; -int ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD = 0; -int ECORE_CON_EVENT_URL_PROGRESS_UPLOAD = 0; +int ECORE_CON_EVENT_URL_PROGRESS = 0; #ifdef HAVE_CURL static int _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); @@ -61,10 +62,11 @@ static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlno static void _ecore_con_event_url_free(void *data __UNUSED__, void *ev); static int _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match); -static CURLM *curlm = NULL; -static Ecore_List *_url_con_list = NULL; -static fd_set _current_fd_set; -static int init_count = 0; +static Ecore_Idler *_fd_idler_handler = NULL; +static Ecore_List *_url_con_list = NULL; +static CURLM *curlm = NULL; +static fd_set _current_fd_set; +static int init_count = 0; struct _Ecore_Con_Url_Event { @@ -114,8 +116,7 @@ ecore_con_url_init(void) { ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); - ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD = ecore_event_type_new(); - ECORE_CON_EVENT_URL_PROGRESS_UPLOAD = ecore_event_type_new(); + ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new(); } if (!_url_con_list) @@ -168,7 +169,7 @@ ecore_con_url_shutdown(void) if (!ecore_list_empty_is(_url_con_list)) { Ecore_Con_Url *url_con; - while ((url_con = ecore_list_first_remove(_url_con_list))) + while ((url_con = ecore_list_first(_url_con_list))) { ecore_con_url_destroy(url_con); } @@ -230,6 +231,11 @@ ecore_con_url_new(const char *url) curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEOUT, 300); curl_easy_setopt(url_con->curl_easy, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate"); + + url_con->fd = -1; + url_con->write_fd = -1; + return url_con; #else return NULL; @@ -237,6 +243,15 @@ ecore_con_url_new(const char *url) #endif } +static int +_ecore_con_url_compare_cb(const void *data1, const void *data2) +{ + const void *url_con1 = data1; + const void *url_con2 = data2; + + return (url_con1 == url_con2) ? 0 : 1; +} + /** * Frees the Ecore_Con_Url. * @return FIXME: To be documented. @@ -255,11 +270,20 @@ ecore_con_url_destroy(Ecore_Con_Url *url_con) ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE); if (url_con->fd_handler) - ecore_main_fd_handler_del(url_con->fd_handler); + { + ecore_main_fd_handler_del(url_con->fd_handler); + url_con->fd = -1; + } if (url_con->curl_easy) { if (url_con->active) - curl_multi_remove_handle(curlm, url_con->curl_easy); + { + if (ecore_list_find(_url_con_list, _ecore_con_url_compare_cb, url_con) == url_con) + ecore_list_remove(_url_con_list); + url_con->active = 0; + + curl_multi_remove_handle(curlm, url_con->curl_easy); + } curl_easy_cleanup(url_con->curl_easy); } curl_slist_free_all(url_con->headers); @@ -371,6 +395,43 @@ ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t #endif } +/** + * FIXME: To be documented. + * @return FIXME: To be documented. + * @ingroup Ecore_Con_Url_Group + */ +EAPI void +ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd) +{ +#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_set"); + return ; + } + url_con->write_fd = fd; +#endif +} + +/** + * FIXME: To be documented. + * @return FIXME: To be documented. + * @ingroup Ecore_Con_Url_Group + */ +EAPI int +ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con) +{ +#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_received_bytes_get"); + return -1; + } + + return url_con->received; +#endif +} + /** * FIXME: To be documented. * @return FIXME: To be documented. @@ -440,6 +501,57 @@ ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *cont } #ifdef HAVE_CURL +static int +_ecore_con_url_suspend_fd_handler(void) +{ + Ecore_Con_Url *url_con; + int deleted = 0; + + if (!_url_con_list) + return 0; + + ecore_list_first_goto(_url_con_list); + while ((url_con = ecore_list_current(_url_con_list))) + { + if (url_con->active && url_con->fd_handler) + { + ecore_main_fd_handler_del(url_con->fd_handler); + url_con->fd_handler = NULL; + deleted++; + } + ecore_list_next(_url_con_list); + } + + return deleted; +} + +static int +_ecore_con_url_restart_fd_handler(void) +{ + Ecore_Con_Url *url_con; + int activated = 0; + + if (!_url_con_list) + return 0; + + ecore_list_first_goto(_url_con_list); + while ((url_con = ecore_list_current(_url_con_list))) + { + if (url_con->fd_handler == NULL + && url_con->fd != -1) + { + url_con->fd_handler = ecore_main_fd_handler_add(url_con->fd, + url_con->flags, + _ecore_con_url_fd_handler, + NULL, NULL, NULL); + activated++; + } + ecore_list_next(_url_con_list); + } + + return activated; +} + static size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp) { @@ -448,15 +560,50 @@ _ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp) size_t real_size = size * nmemb; url_con = (Ecore_Con_Url *)userp; - e = malloc(sizeof(Ecore_Con_Event_Url_Data) + sizeof(unsigned char) * (real_size - 1)); - if (e) + + if (!url_con) return -1; + if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) { - e->url_con = url_con; - e->size = real_size; - memcpy(e->data, buffer, real_size); - ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, - _ecore_con_event_url_free, NULL); + ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_cb"); + return -1; } + + url_con->received += real_size; + + if (url_con->write_fd < 0) + { + e = malloc(sizeof(Ecore_Con_Event_Url_Data) + sizeof(unsigned char) * (real_size - 1)); + if (e) + { + e->url_con = url_con; + e->size = real_size; + memcpy(e->data, buffer, real_size); + ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, + _ecore_con_event_url_free, NULL); + } + } + else + { + ssize_t count = 0; + size_t total_size = real_size; + size_t offset = 0; + + while (total_size > 0) + { + count = write(url_con->write_fd, (char*) buffer + offset, total_size); + if (count < 0) + { + if (errno != EAGAIN && errno != EINTR) + return -1; + } + else + { + total_size -= count; + offset += count; + } + } + } + return real_size; } @@ -479,12 +626,21 @@ _ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp) static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { - Ecore_Con_Url *url_con; + Ecore_Con_Event_Url_Progress *e; + Ecore_Con_Url *url_con; url_con = clientp; - ECORE_CON_URL_TRANSMISSION(Download, ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD, url_con, dltotal, dlnow); - ECORE_CON_URL_TRANSMISSION(Upload, ECORE_CON_EVENT_URL_PROGRESS_UPLOAD, url_con, ultotal, ulnow); + e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress)); + if (e) + { + e->url_con = url_con; + e->down.total = dltotal; + e->down.now = dlnow; + e->up.total = ultotal; + e->up.now = ulnow; + ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, _ecore_con_event_url_free, NULL); + } return 0; } @@ -493,6 +649,7 @@ static int _ecore_con_url_perform(Ecore_Con_Url *url_con) { fd_set read_set, write_set, exc_set; + double start; int fd_max; int fd; int flags; @@ -501,8 +658,10 @@ _ecore_con_url_perform(Ecore_Con_Url *url_con) ecore_list_append(_url_con_list, url_con); + start = ecore_time_get(); url_con->active = 1; curl_multi_add_handle(curlm, url_con->curl_easy); + /* This one can't be stopped, or the download never start. */ while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); completed_immediately = _ecore_con_url_process_completed_jobs(url_con); @@ -527,9 +686,12 @@ _ecore_con_url_perform(Ecore_Con_Url *url_con) if (flags) { FD_SET(fd, &_current_fd_set); + url_con->fd = fd; + url_con->flags = flags; url_con->fd_handler = ecore_main_fd_handler_add(fd, flags, _ecore_con_url_fd_handler, NULL, NULL, NULL); + break; } } } @@ -538,6 +700,7 @@ _ecore_con_url_perform(Ecore_Con_Url *url_con) /* Failed to set up an fd_handler */ curl_multi_remove_handle(curlm, url_con->curl_easy); url_con->active = 0; + url_con->fd = -1; return 0; } } @@ -546,14 +709,41 @@ _ecore_con_url_perform(Ecore_Con_Url *url_con) } static int -_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) +_ecore_con_url_idler_handler(void *data) { - int still_running; + double start; + int done = 1; + int still_running; - /* FIXME: Can this run for a long time? Maybe limit how long it can run */ - while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); + start = ecore_time_get(); + while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM) + /* make this 1/20th of a second to keep interactivity high */ + if ((ecore_time_get() - start) > 0.2) + { + done = 0; + break; + } _ecore_con_url_process_completed_jobs(NULL); + + if (done) + { + _ecore_con_url_restart_fd_handler(); + _fd_idler_handler = NULL; + return 0; + } + + return 1; +} + +static int +_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + _ecore_con_url_suspend_fd_handler(); + + if (_fd_idler_handler == NULL) + _fd_idler_handler = ecore_idler_add(_ecore_con_url_idler_handler, NULL); + return 1; } @@ -580,11 +770,12 @@ _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match) if (url_con_to_match && (url_con == url_con_to_match)) { job_matched = 1; } - if (url_con->fd_handler) + if (url_con->fd != -1) { - FD_CLR(ecore_main_fd_handler_fd_get(url_con->fd_handler), - &_current_fd_set); - ecore_main_fd_handler_del(url_con->fd_handler); + FD_CLR(url_con->fd, &_current_fd_set); + if (url_con->fd_handler) + ecore_main_fd_handler_del(url_con->fd_handler); + url_con->fd = -1; url_con->fd_handler = NULL; } ecore_list_remove(_url_con_list); diff --git a/legacy/ecore/src/lib/ecore_file/Makefile.am b/legacy/ecore/src/lib/ecore_file/Makefile.am index 3e52f502a9..05e1ee3180 100644 --- a/legacy/ecore/src/lib/ecore_file/Makefile.am +++ b/legacy/ecore/src/lib/ecore_file/Makefile.am @@ -2,6 +2,7 @@ MAINTAINERCLEANFILES = Makefile.in AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_con \ -I$(top_builddir)/src/lib/ecore \ @CURL_CFLAGS@ @@ -21,7 +22,8 @@ ecore_file_download.c libecore_file_la_LIBADD = \ $(top_builddir)/src/lib/ecore/libecore.la \ -@CURL_LIBS@ @ecore_file_win32_lib@ @winsock_libs@ +$(top_builddir)/src/lib/ecore_con/libecore_con.la \ +@ecore_file_win32_lib@ @winsock_libs@ libecore_file_la_LDFLAGS = @create_shared_lib@ -version-info @version_info@ 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 85ede05bb6..bda540fb2e 100644 --- a/legacy/ecore/src/lib/ecore_file/ecore_file_download.c +++ b/legacy/ecore/src/lib/ecore_file/ecore_file_download.c @@ -1,111 +1,98 @@ /* * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 */ +#include "Ecore_Con.h" #include "ecore_file_private.h" -static int init = 0; - -#ifdef HAVE_CURL -#include - -typedef struct _Ecore_File_Download_Job Ecore_File_Download_Job; +#define ECORE_MAGIC_FILE_DOWNLOAD_JOB 0xf7427cb8 +typedef struct _Ecore_File_Download_Job Ecore_File_Download_Job; struct _Ecore_File_Download_Job { - Ecore_Fd_Handler *fd_handler; - CURL *curl; - void (*completion_cb)(void *data, const char *file, int status); - int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow); - void *data; - FILE *file; - char *dst; + ECORE_MAGIC; + + Ecore_Con_Url *url_con; + FILE *file; + + char *dst; + + void (*completion_cb)(void *data, const char *file, int status); + + int (*progress_cb) (void *data, const char *file, + long int dltotal, long int dlnow, + long int ultotal, long int ulnow); }; +#ifdef HAVE_CURL Ecore_File_Download_Job *_ecore_file_download_curl(const char *url, const char *dst, void (*completion_cb)(void *data, const char *file, int status), int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow), void *data); static int _ecore_file_download_curl_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); -static CURLM *curlm; -static Ecore_List *_job_list; -static fd_set _current_fd_set; +static void _ecore_file_download_abort(Ecore_File_Download_Job *job); + +static int _ecore_file_download_url_complete_cb(void *data, int type, void *event); +static int _ecore_file_download_url_progress_cb(void *data, int type, void *event); #endif -int +static int init = 0; +static Ecore_Event_Handler *_url_complete_handler = NULL; +static Ecore_Event_Handler *_url_progress_download = NULL; +static Ecore_List *_job_list; + +EAPI int ecore_file_download_init(void) { - if (++init != 1) return init; + ecore_con_url_init(); -#ifdef HAVE_CURL - FD_ZERO(&_current_fd_set); - _job_list = ecore_list_new(); - if (!_job_list) return --init; - - if (curl_global_init(CURL_GLOBAL_NOTHING)) return 0; - - curlm = curl_multi_init(); - if (!curlm) + if (init++ == 0) { - ecore_list_destroy(_job_list); - _job_list = NULL; - return --init; +#ifdef HAVE_CURL + _url_complete_handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _ecore_file_download_url_complete_cb, NULL); + _url_progress_download = ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS, _ecore_file_download_url_progress_cb, NULL); +#endif } -#endif - return init; + if (!_job_list) + { + _job_list = ecore_list_new(); + if (!_job_list) return 0; + } + + return 1; } -int +EAPI int ecore_file_download_shutdown(void) { - if (--init != 0) return init; -#ifdef HAVE_CURL - Ecore_File_Download_Job *job; - - if (!ecore_list_empty_is(_job_list)) + if (--init == 0) { - ecore_list_first_goto(_job_list); - while ((job = ecore_list_next(_job_list))) - { - ecore_main_fd_handler_del(job->fd_handler); - curl_multi_remove_handle(curlm, job->curl); - curl_easy_cleanup(job->curl); - fclose(job->file); - free(job->dst); - free(job); - } + ecore_event_handler_del(_url_complete_handler); + ecore_event_handler_del(_url_progress_download); + _url_complete_handler = NULL; + _url_progress_download = NULL; + + ecore_list_destroy(_job_list); } - ecore_list_destroy(_job_list); - curl_multi_cleanup(curlm); - curl_global_cleanup(); -#endif - return init; + + return ecore_con_url_shutdown(); } -void +EAPI void ecore_file_download_abort_all(void) { -#ifdef HAVE_CURL - Ecore_File_Download_Job *job; - - if (!_job_list) - return; - - ecore_list_first_goto(_job_list); - while ((job = ecore_list_next(_job_list))) + if (!ecore_list_empty_is(_job_list)) { - ecore_main_fd_handler_del(job->fd_handler); - curl_multi_remove_handle(curlm, job->curl); - curl_easy_cleanup(job->curl); - fclose(job->file); - free(job->dst); - free(job); + Ecore_File_Download_Job *job; + + while ((job = ecore_list_first_remove(_job_list))) + { + _ecore_file_download_abort(job); + } } ecore_list_clear(_job_list); -#endif } - /** * Download @p url to the given @p dst * @param url The complete url to download @@ -192,200 +179,108 @@ ecore_file_download_protocol_available(const char *protocol) } #ifdef HAVE_CURL +static int +_ecore_file_download_url_compare_job(const void *data1, const void *data2) +{ + const Ecore_File_Download_Job *job = data1; + const Ecore_Con_Url *url = data2; + + if (job->url_con == url) return 0; + return -1; +} + +static int +_ecore_file_download_url_complete_cb(void *data, int type, void *event) +{ + Ecore_Con_Event_Url_Complete *ev = event; + Ecore_File_Download_Job *job; + + job = ecore_list_find(_job_list, _ecore_file_download_url_compare_job, ev->url_con); + if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return 1; + + ecore_list_remove(_job_list); + + if (job->completion_cb) + job->completion_cb(ecore_con_url_data_get(job->url_con), job->dst, !ev->status); + + _ecore_file_download_abort(job); + + return 0; +} + +static int +_ecore_file_download_url_progress_cb(void *data, int type, void *event) +{ /* this reports the downloads progress. if we return 0, then download * continues, if we return anything else, then the download stops */ -static int -_ecore_file_download_curl_progress_func(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) -{ - Ecore_File_Download_Job *job; + Ecore_Con_Event_Url_Progress *ev = event; + Ecore_File_Download_Job *job; - job = clientp; + job = ecore_list_find(_job_list, _ecore_file_download_url_compare_job, ev->url_con); + if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return 1; + + if (job->progress_cb) + if (job->progress_cb(ecore_con_url_data_get(job->url_con), job->dst, + (long int) ev->down.total, (long int) ev->down.now, + (long int) ev->up.total, (long int) ev->up.now) != 0) + { + ecore_list_remove(_job_list); + _ecore_file_download_abort(job); + } - if(job->progress_cb) - return job->progress_cb(job->data, job->dst, (long int)dltotal, (long int)dlnow, (long int)ultotal, (long int)ulnow); return 0; } +static void +_ecore_file_download_abort(Ecore_File_Download_Job *job) +{ + ecore_con_url_destroy(job->url_con); + fclose(job->file); + free(job->dst); + free(job); +} + Ecore_File_Download_Job * _ecore_file_download_curl(const char *url, const char *dst, void (*completion_cb)(void *data, const char *file, int status), int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, - long int ultotal, - long int ulnow), + long int ultotal, long int ulnow), void *data) { - CURLMsg *curlmsg; - fd_set read_set, write_set, exc_set; - int fd_max; - int fd; - int flags; - int n_remaining, still_running; Ecore_File_Download_Job *job; - double start = 0.0; job = calloc(1, sizeof(Ecore_File_Download_Job)); if (!job) return NULL; + ECORE_MAGIC_SET(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB); + job->file = fopen(dst, "wb"); if (!job->file) { free(job); return NULL; } - job->curl = curl_easy_init(); - if (!job->curl) + job->url_con = ecore_con_url_new(url); + if (!job->url_con) { fclose(job->file); free(job); return NULL; } - curl_easy_setopt(job->curl, CURLOPT_URL, url); - curl_easy_setopt(job->curl, CURLOPT_WRITEDATA, job->file); - curl_easy_setopt(job->curl, CURLOPT_FOLLOWLOCATION, TRUE); - - if (progress_cb) - { - curl_easy_setopt(job->curl, CURLOPT_NOPROGRESS, FALSE); - curl_easy_setopt(job->curl, CURLOPT_PROGRESSDATA, job); - curl_easy_setopt(job->curl, CURLOPT_PROGRESSFUNCTION, _ecore_file_download_curl_progress_func); - } + ecore_con_url_fd_set(job->url_con, fileno(job->file)); + ecore_con_url_data_set(job->url_con, data); + + job->dst = strdup(dst); - job->data = data; job->completion_cb = completion_cb; job->progress_cb = progress_cb; - job->dst = strdup(dst); ecore_list_append(_job_list, job); - curl_multi_add_handle(curlm, job->curl); - start = ecore_time_get(); - while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM) - { - /* make this 1/100th of a second to keep interactivity high. really - * though this needs to somehow get the fd from curl and use an fd handler - * and thus select - */ - if ((ecore_time_get() - start) > 0.01) break; - } - - /* check for completed jobs */ - while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL) - { - Ecore_File_Download_Job *current; - - if (curlmsg->msg != CURLMSG_DONE) continue; - - /* find the job which is done */ - ecore_list_first_goto(_job_list); - while ((current = ecore_list_current(_job_list))) - { - if (curlmsg->easy_handle == current->curl) - { - /* We have a match -- delete the job */ - if (current == job) - job = NULL; - if (current->fd_handler) - { - FD_CLR(ecore_main_fd_handler_fd_get(current->fd_handler), - &_current_fd_set); - ecore_main_fd_handler_del(current->fd_handler); - } - ecore_list_remove(_job_list); - curl_multi_remove_handle(curlm, current->curl); - curl_easy_cleanup(current->curl); - fclose(current->file); - if (current->completion_cb) - current->completion_cb(current->data, current->dst, - curlmsg->data.result); - free(current->dst); - free(current); - break; - } - ecore_list_next(_job_list); - } - } - - if (job) - { - FD_ZERO(&read_set); - FD_ZERO(&write_set); - FD_ZERO(&exc_set); - - /* Stupid curl, why can't I get the fd to the current added job? */ - curl_multi_fdset(curlm, &read_set, &write_set, &exc_set, &fd_max); - for (fd = 0; fd <= fd_max; fd++) - { - if (!FD_ISSET(fd, &_current_fd_set)) - { - flags = 0; - if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; - if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; - if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; - if (flags) - { - FD_SET(fd, &_current_fd_set); - job->fd_handler = ecore_main_fd_handler_add(fd, flags, - _ecore_file_download_curl_fd_handler, - NULL, NULL, NULL); - } - } - } - if (!job->fd_handler) - { - curl_easy_cleanup(job->curl); - fclose(job->file); - free(job); - job = NULL; - } - } + ecore_con_url_send(job->url_con, NULL, 0, NULL); return job; } - -static int -_ecore_file_download_curl_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) -{ - Ecore_File_Download_Job *job; - CURLMsg *curlmsg; - int n_remaining, still_running; - double start = 0.0; - - start = ecore_time_get(); - while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM) - { - if ((ecore_time_get() - start) > 0.2) break; - } - - /* Loop jobs and check if any are done */ - while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL) - { - if (curlmsg->msg != CURLMSG_DONE) continue; - - /* find the job which is done */ - ecore_list_first_goto(_job_list); - while ((job = ecore_list_current(_job_list))) - { - if (curlmsg->easy_handle == job->curl) - { - /* We have a match -- delete the job */ - FD_CLR(ecore_main_fd_handler_fd_get(job->fd_handler), - &_current_fd_set); - ecore_list_remove(_job_list); - ecore_main_fd_handler_del(job->fd_handler); - curl_multi_remove_handle(curlm, job->curl); - curl_easy_cleanup(job->curl); - fclose(job->file); - if (job->completion_cb) - job->completion_cb(job->data, job->dst, !curlmsg->data.result); - free(job->dst); - free(job); - break; - } - ecore_list_next(_job_list); - } - } - return 1; -} #endif