giant patch refactoring ecore-con-url from bluezery <opowel@gmail.com>
authordiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 5 Dec 2011 06:08:46 +0000 (06:08 +0000)
committerdiscomfitor <discomfitor@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Mon, 5 Dec 2011 06:08:46 +0000 (06:08 +0000)
will it blend?!

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@65888 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/ecore_con/ecore_con_private.h
src/lib/ecore_con/ecore_con_url.c

index f601465..af7ffbd 100644 (file)
@@ -187,14 +187,8 @@ struct _Ecore_Con_Url
    double timestamp;
    void *data;
 
-   Ecore_Fd_Handler *fd_handler;
-   int fd;
-   int flags;
-
    int received;
    int write_fd;
-
-   Eina_Bool active : 1;
 };
 #endif
 
index cfcf095..cf6c216 100644 (file)
@@ -35,8 +35,6 @@ int ECORE_CON_EVENT_URL_COMPLETE = 0;
 int ECORE_CON_EVENT_URL_PROGRESS = 0;
 
 #ifdef HAVE_CURL
-static Eina_Bool _ecore_con_url_fd_handler(void             *data,
-                                           Ecore_Fd_Handler *fd_handler);
 static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con);
 static size_t    _ecore_con_url_header_cb(void  *ptr,
                                           size_t size,
@@ -57,50 +55,17 @@ static size_t _ecore_con_url_read_cb(void  *ptr,
                                      void  *stream);
 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 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 Ecore_Idler *_fd_idler_handler = NULL;
 static Eina_List *_url_con_list = NULL;
+static Eina_List *_fd_hd_list = NULL;
 static CURLM *_curlm = NULL;
 static fd_set _current_fd_set;
 static int _init_count = 0;
 static Ecore_Timer *_curl_timeout = NULL;
 static Eina_Bool pipelining = EINA_FALSE;
 
-typedef struct _Ecore_Con_Url_Event Ecore_Con_Url_Event;
-struct _Ecore_Con_Url_Event
-{
-   int   type;
-   void *ev;
-};
-
-static Eina_Bool
-_url_complete_idler_cb(void *data)
-{
-   Ecore_Con_Url_Event *lev;
-
-   lev = data;
-   ecore_event_add(lev->type, lev->ev, _ecore_con_event_url_free, NULL);
-   free(lev);
-
-   return ECORE_CALLBACK_CANCEL;
-}
-
-static void
-_url_complete_push_event(int   type,
-                         void *ev)
-{
-   Ecore_Con_Url_Event *lev;
-
-   lev = malloc(sizeof(Ecore_Con_Url_Event));
-   lev->type = type;
-   lev->ev = ev;
-
-   ecore_idler_add(_url_complete_idler_cb, lev);
-}
-
 #endif
 
 /**
@@ -113,51 +78,30 @@ EAPI int
 ecore_con_url_init(void)
 {
 #ifdef HAVE_CURL
-   _init_count++;
-
-   if (_init_count > 1)
-     return _init_count;
+   if (++_init_count > 1) return _init_count;
 
-   if (!ECORE_CON_EVENT_URL_DATA)
-     {
-        ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
-        ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
-        ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new();
-     }
+   if (!ECORE_CON_EVENT_URL_DATA)     ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
+   if (!ECORE_CON_EVENT_URL_COMPLETE) ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
+   if (!ECORE_CON_EVENT_URL_PROGRESS) ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new();
 
    if (!_curlm)
      {
         long ms;
 
-        FD_ZERO(&_current_fd_set);
-        if (curl_global_init(CURL_GLOBAL_ALL))
-          {
-             while (_url_con_list)
-               ecore_con_url_free(eina_list_data_get(_url_con_list));
-             return 0;
-          }
+        // curl_global_init() is not thread safe!
+        if (curl_global_init(CURL_GLOBAL_ALL)) return --_init_count;
 
         _curlm = curl_multi_init();
-        if (!_curlm)
-          {
-             while (_url_con_list)
-               ecore_con_url_free(eina_list_data_get(_url_con_list));
-
-             _init_count--;
-             return 0;
-          }
+        if (!_curlm)  return --_init_count;
 
         curl_multi_timeout(_curlm, &ms);
-        if (ms <= 0)
-          ms = 1000;
+        if (ms <= 0) ms = 100;
 
-        _curl_timeout =
-          ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler,
-                          (void *)0xACE);
+        _curl_timeout = ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler, (void *)0xACE);
         ecore_timer_freeze(_curl_timeout);
      }
 
-   return 1;
+   return _init_count;
 #else
    return 0;
 #endif
@@ -167,34 +111,31 @@ EAPI int
 ecore_con_url_shutdown(void)
 {
 #ifdef HAVE_CURL
-   if (!_init_count)
-     return 0;
-
-   _init_count--;
-
-   if (_init_count != 0)
-     return _init_count;
-
-   if (_fd_idler_handler)
-     ecore_idler_del(_fd_idler_handler);
-
-   _fd_idler_handler = NULL;
+   if (_init_count == 0) return 0;
 
-   if (_curl_timeout)
-     ecore_timer_del(_curl_timeout);
-
-   _curl_timeout = NULL;
+   if (--_init_count == 0)
+     {
+        Ecore_Con_Url *con_url;
+        Ecore_Fd_Handler *fd_handler;
 
-   while (_url_con_list)
-     ecore_con_url_free(eina_list_data_get(_url_con_list));
+        if (_curl_timeout)
+          {
+             ecore_timer_del(_curl_timeout);
+             _curl_timeout = NULL;
+          }
 
-   if (_curlm)
-     {
-        curl_multi_cleanup(_curlm);
-        _curlm = NULL;
-     }
+        FD_ZERO(&_current_fd_set);
+        EINA_LIST_FREE(_url_con_list, con_url) ecore_con_url_free(con_url);
+        EINA_LIST_FREE(_fd_hd_list, fd_handler) ecore_main_fd_handler_del(fd_handler);
 
-   curl_global_cleanup();
+        if (_curlm)
+          {
+             curl_multi_cleanup(_curlm);
+             _curlm = NULL;
+          }
+        curl_global_cleanup();
+   }
+   return _init_count;
 #endif
    return 1;
 }
@@ -237,7 +178,6 @@ ecore_con_url_new(const char *url)
    if (!url_con)
      return NULL;
 
-   url_con->fd = -1;
    url_con->write_fd = -1;
 
    url_con->curl_easy = curl_easy_init();
@@ -344,31 +284,16 @@ ecore_con_url_free(Ecore_Con_Url *url_con)
      }
 
    ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
-   if(url_con->fd != -1)
-     {
-        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;
-     }
 
    if (url_con->curl_easy)
      {
-        // FIXME: For an unknown reason, progress continue to arrive after destruction
-        // this prevent any further call to the callback.
         curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL);
         curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE);
 
-        if (url_con->active)
+        if (eina_list_data_find(_url_con_list, url_con))
           {
-             url_con->active = EINA_FALSE;
-
              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));
+             if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
           }
 
         curl_easy_cleanup(url_con->curl_easy);
@@ -415,8 +340,7 @@ ecore_con_url_url_set(Ecore_Con_Url *url_con,
         return EINA_FALSE;
      }
 
-   if (url_con->active)
-     return EINA_FALSE;
+   if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE;
 
    eina_stringshare_replace(&url_con->url, url);
 
@@ -668,8 +592,7 @@ _ecore_con_url_send(Ecore_Con_Url *url_con,
         return EINA_FALSE;
      }
 
-   if (url_con->active)
-     return EINA_FALSE;
+   if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE;
 
    if (!url_con->url)
      return EINA_FALSE;
@@ -787,8 +710,7 @@ ecore_con_url_ftp_upload(Ecore_Con_Url *url_con,
         return EINA_FALSE;
      }
 
-   if (url_con->active)
-     return EINA_FALSE;
+   if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE;
 
    if (!url_con->url)
      return EINA_FALSE;
@@ -1021,8 +943,7 @@ ecore_con_url_verbose_set(Ecore_Con_Url *url_con,
         return;
      }
 
-   if (url_con->active)
-     return;
+   if (eina_list_data_find(_url_con_list, url_con)) return;
 
    if (!url_con->url)
      return;
@@ -1047,8 +968,7 @@ ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con,
         return;
      }
 
-   if (url_con->active)
-     return;
+   if (eina_list_data_find(_url_con_list, url_con)) return;
 
    if (!url_con->url)
      return;
@@ -1085,8 +1005,7 @@ ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con,
         return;
      }
 
-   if (url_con->active)
-     return;
+   if (eina_list_data_find(_url_con_list, url_con)) return;
 
    if (!url_con->url)
      return;
@@ -1129,7 +1048,7 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path)
              return -1;
      }
 
-   if (url_con->active) return -1;
+   if (eina_list_data_find(_url_con_list, url_con)) return -1;
    if (!url_con->url) return -1;
    if (ca_path == NULL)
      res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0);
@@ -1154,54 +1073,6 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path)
  */
 
 #ifdef HAVE_CURL
-static int
-_ecore_con_url_suspend_fd_handler(void)
-{
-   Eina_List *l;
-   Ecore_Con_Url *url_con;
-   int deleted = 0;
-
-   if (!_url_con_list)
-     return 0;
-
-   EINA_LIST_FOREACH(_url_con_list, l, url_con)
-     {
-        if (url_con->active && url_con->fd_handler)
-          {
-             ecore_main_fd_handler_del(url_con->fd_handler);
-             url_con->fd_handler = NULL;
-             deleted++;
-          }
-     }
-
-   return deleted;
-}
-
-static int
-_ecore_con_url_restart_fd_handler(void)
-{
-   Eina_List *l;
-   Ecore_Con_Url *url_con;
-   int activated = 0;
-
-   if (!_url_con_list)
-     return 0;
-
-   EINA_LIST_FOREACH(_url_con_list, l, url_con)
-     {
-        if (!url_con->fd_handler && 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++;
-          }
-     }
-
-   return activated;
-}
-
 static size_t
 _ecore_con_url_data_cb(void  *buffer,
                        size_t size,
@@ -1235,8 +1106,7 @@ _ecore_con_url_data_cb(void  *buffer,
              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_event_add(ECORE_CON_EVENT_URL_DATA, e, _ecore_con_event_url_free, NULL);
           }
      }
    else
@@ -1266,22 +1136,6 @@ _ecore_con_url_data_cb(void  *buffer,
    return real_size;
 }
 
-#define ECORE_CON_URL_TRANSMISSION(Transmit, Event, Url_con, Total, Now)   \
-  {                                                                        \
-     Ecore_Con_Event_Url_Progress *e;                                      \
-     if ((Total != 0) || (Now != 0))                                       \
-       {                                                                   \
-          e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress));             \
-          if (e)                                                           \
-            {                                                              \
-               e->url_con = url_con;                                       \
-               e->total = Total;                                           \
-               e->now = Now;                                               \
-               ecore_event_add(Event, e, _ecore_con_event_url_free, NULL); \
-            }                                                              \
-       }                                                                   \
-  }
-
 static size_t
 _ecore_con_url_header_cb(void  *ptr,
                          size_t size,
@@ -1324,8 +1178,7 @@ _ecore_con_url_progress_cb(void  *clientp,
         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);
+        ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, _ecore_con_event_url_free, NULL);
      }
 
    return 0;
@@ -1358,208 +1211,196 @@ _ecore_con_url_read_cb(void  *ptr,
    return retcode;
 }
 
-static Eina_Bool
-_ecore_con_url_perform(Ecore_Con_Url *url_con)
+static void
+_ecore_con_url_info_read(void)
 {
-   fd_set read_set, write_set, exc_set;
-   int fd_max, fd;
-   int flags, still_running;
-   int completed_immediately = 0;
-   CURLMcode ret;
-
-   _url_con_list = eina_list_append(_url_con_list, url_con);
-
-   url_con->active = EINA_TRUE;
-   curl_multi_add_handle(_curlm, url_con->curl_easy);
-   curl_multi_perform(_curlm, &still_running);
-
-   completed_immediately = _ecore_con_url_process_completed_jobs(url_con);
+   CURLMsg *curlmsg;
+   int n_remaining;
 
-   if (!completed_immediately)
+   while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining)))
      {
-        if (url_con->fd_handler)
-          ecore_main_fd_handler_del(url_con->fd_handler);
-
-        url_con->fd_handler = NULL;
-
-        /* url_con still active -- set up an fd_handler */
-        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? */
-        ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set,
-                               &fd_max);
-        if (ret != CURLM_OK)
+        if (curlmsg->msg == CURLMSG_DONE)
           {
-             ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret));
-             return EINA_FALSE;
-          }
+             Eina_List *l, *ll;
+             Ecore_Con_Url *url_con;
 
-        for (fd = 0; fd <= fd_max; fd++)
-          {
-             if (!FD_ISSET(fd, &_current_fd_set))
+             EINA_LIST_FOREACH_SAFE(_url_con_list, l, ll, url_con)
                {
-                  flags = 0;
-                  if (FD_ISSET(fd, &read_set))
-                    flags |= ECORE_FD_READ;
-
-                  if (FD_ISSET(fd, &write_set))
-                    flags |= ECORE_FD_WRITE;
+                  if (curlmsg->easy_handle == url_con->curl_easy)
+                    {
+                       CURLMcode ret;
+                       Ecore_Con_Event_Url_Complete *e;
 
-                  if (FD_ISSET(fd, &exc_set))
-                    flags |= ECORE_FD_ERROR;
+                       e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
+                       if (e)
+                         {
+                            e->url_con = url_con;
+                            e->status = 0;
+                            if (curlmsg->data.result == CURLE_OK)
+                              {
+                                 long status; /* curl API uses long, not int */
+                                 status = 0;
+                                 curl_easy_getinfo(curlmsg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
+                                 e->status = status;
+                              }
+                            ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, _ecore_con_event_url_free, NULL);
+                         }
 
-                  if (flags)
-                    {
-                       long ms = 0;
-
-                       ret = curl_multi_timeout(_curlm, &ms);
-                       if (ret != CURLM_OK)
-                         ERR("curl_multi_timeout failed: %s",
-                             curl_multi_strerror(ret));
-
-                       if (ms == 0)
-                         ms = 1000;
-
-                       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);
+                       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);
                        break;
                     }
                }
           }
-        if (!url_con->fd_handler)
-          {
-             /* Failed to set up an fd_handler */
-              ecore_timer_freeze(_curl_timeout);
-
-              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->active = EINA_FALSE;
-              url_con->fd = -1;
-              return EINA_FALSE;
-          }
-
-        ecore_timer_thaw(_curl_timeout);
      }
-
-   return EINA_TRUE;
 }
 
-static Eina_Bool
-_ecore_con_url_idler_handler(void *data)
+static void
+_ecore_con_url_curl_clear(void)
 {
-   int done, still_running;
-
-   done = (curl_multi_perform(_curlm, &still_running) != CURLM_CALL_MULTI_PERFORM);
-
-   _ecore_con_url_process_completed_jobs(NULL);
+   Ecore_Con_Url *url_con;
 
-   if (done)
+   FD_ZERO(&_current_fd_set);
+   if (_fd_hd_list)
      {
-        _ecore_con_url_restart_fd_handler();
-        _fd_idler_handler = NULL;
+        Ecore_Fd_Handler *fd_handler;
+        EINA_LIST_FREE(_fd_hd_list, fd_handler)
+          {
+             int fd = ecore_main_fd_handler_fd_get(fd_handler);
+             FD_CLR(fd, &_current_fd_set);
+             // FIXME: ecore_main_fd_handler_del() sometimes give errors
+             // because curl do not make fd itself controlled by users, but it can be ignored.
+             ecore_main_fd_handler_del(fd_handler);
+          }
+     }
 
-        if (!_url_con_list)
-          ecore_timer_freeze(_curl_timeout);
+   EINA_LIST_FREE(_url_con_list, url_con)
+     {
+        CURLMcode ret;
+        Ecore_Con_Event_Url_Complete *e;
 
-        return data ==
-               (void *)0xACE ? ECORE_CALLBACK_RENEW : ECORE_CALLBACK_CANCEL;
+        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);
+          }
+        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));
      }
-
-   return ECORE_CALLBACK_RENEW;
 }
 
 static Eina_Bool
-_ecore_con_url_fd_handler(void *data                   __UNUSED__,
-                          Ecore_Fd_Handler *fd_handler __UNUSED__)
+_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
 {
-   _ecore_con_url_suspend_fd_handler();
-
-   if (!_fd_idler_handler)
-     _fd_idler_handler = ecore_idler_add(
-         _ecore_con_url_idler_handler, NULL);
-
+   if (_fd_hd_list)
+     {
+        Ecore_Fd_Handler *fd_handler;
+        EINA_LIST_FREE(_fd_hd_list, fd_handler)
+          {
+             int fd = ecore_main_fd_handler_fd_get(fd_handler);
+             FD_CLR(fd, &_current_fd_set);
+             // FIXME: ecore_main_fd_handler_del() sometimes give errors
+             // because curl do not make fd itself controlled by users, but it can be ignored.
+             ecore_main_fd_handler_del(fd_handler);
+          }
+     }
+   ecore_timer_thaw(_curl_timeout);
    return ECORE_CALLBACK_RENEW;
 }
 
-static int
-_ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match)
+static void
+_ecore_con_url_fdset(void)
 {
-   Eina_List *l;
-   Ecore_Con_Url *url_con;
-   Ecore_Con_Event_Url_Complete *e;
-   CURLMsg *curlmsg;
    CURLMcode ret;
-   int n_remaining;
-   int job_matched = 0;
+   fd_set read_set, write_set, exc_set;
+   int fd, fd_max;
+   Ecore_Fd_Handler *fd_handler;
 
-   /* Loop jobs and check if any are done */
-   while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining)))
+   FD_ZERO(&read_set);
+   FD_ZERO(&write_set);
+   FD_ZERO(&exc_set);
+
+   ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set, &fd_max);
+   if (ret != CURLM_OK)
      {
-        if (curlmsg->msg != CURLMSG_DONE)
-          continue;
+        ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret));
+        return;
+     }
 
-        /* find the job which is done */
-        EINA_LIST_FOREACH(_url_con_list, l, url_con)
+   for (fd = 0; fd <= fd_max; fd++)
+     {
+        int 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)
           {
-             if (curlmsg->easy_handle == url_con->curl_easy)
+             if (!FD_ISSET(fd, &_current_fd_set))
                {
-                  if (url_con_to_match &&
-                      (url_con == url_con_to_match))
-                    job_matched = 1;
-
-                  if(url_con->fd != -1)
-                    {
-                       FD_CLR(url_con->fd, &_current_fd_set);
-                       if (url_con->fd_handler)
-                         ecore_main_fd_handler_del(
-                           url_con->fd_handler);
+                  FD_SET(fd, &_current_fd_set);
+                  fd_handler = ecore_main_fd_handler_add(fd, flags, _ecore_con_url_fd_handler, NULL, NULL, NULL);
+                  if (fd_handler) _fd_hd_list = eina_list_append(_fd_hd_list, fd_handler);
+                  ecore_timer_freeze(_curl_timeout);
+               }
+          }
+     }
+}
 
-                       url_con->fd = -1;
-                       url_con->fd_handler = NULL;
-                    }
+static Eina_Bool
+_ecore_con_url_idler_handler(void *data __UNUSED__)
+{
+   int still_running;
+   CURLMcode ret;
 
-                  _url_con_list = eina_list_remove(_url_con_list, url_con);
-                  url_con->active = EINA_FALSE;
-                  e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
-                  if (e)
-                    {
-                       e->url_con = url_con;
-                       e->status = 0;
-                       if (curlmsg->data.result == CURLE_OK)
-                         {
-                            long status; /* curl API uses long, not int */
+   ret = curl_multi_perform(_curlm, &still_running);
+   if (ret != CURLM_OK)
+     {
+        ERR("curl_multi_perform() failed: %s", curl_multi_strerror(ret));
+        _ecore_con_url_curl_clear();
+        ecore_timer_freeze(_curl_timeout);
+        return ECORE_CALLBACK_RENEW;
+     }
+   if (ret == CURLM_CALL_MULTI_PERFORM)
+     {
+        DBG("Call multiperform again");
+        return ECORE_CALLBACK_RENEW;
+     }
 
-                            status = 0;
-                            curl_easy_getinfo(curlmsg->easy_handle,
-                                              CURLINFO_RESPONSE_CODE,
-                                              &status);
-                            e->status = status;
-                         }
+   _ecore_con_url_info_read();
+   if (still_running)
+     {
+        DBG("multiperform is still_running");
+        _ecore_con_url_fdset();
+     }
+   else
+     {
+        DBG("multiperform ended");
+        _ecore_con_url_curl_clear();
+        ecore_timer_freeze(_curl_timeout);
+     }
 
-                       _url_complete_push_event(ECORE_CON_EVENT_URL_COMPLETE, e);
-                    }
+   return ECORE_CALLBACK_RENEW;
+}
 
-                  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));
+static Eina_Bool
+_ecore_con_url_perform(Ecore_Con_Url *url_con)
+{
+   CURLMcode ret;
 
-                  break;
-               }
-          }
+   ret = curl_multi_add_handle(_curlm, url_con->curl_easy);
+   if (ret != CURLM_OK)
+     {
+        ERR("curl_multi_add_handle() failed: %s", curl_multi_strerror(ret));
+        return EINA_FALSE;
      }
 
-   return job_matched;
+   _url_con_list = eina_list_append(_url_con_list, url_con);
+   ecore_timer_thaw(_curl_timeout);
+
+   return EINA_TRUE;
 }
 
 static void