aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore_con/ecore_con_url.c')
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_url.c671
1 files changed, 347 insertions, 324 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
index 709b554..05f0678 100644
--- a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
@@ -30,41 +30,31 @@
30#include "Ecore_Con.h" 30#include "Ecore_Con.h"
31#include "ecore_con_private.h" 31#include "ecore_con_private.h"
32 32
33#define CURL_MIN_TIMEOUT 100
34
33int ECORE_CON_EVENT_URL_DATA = 0; 35int ECORE_CON_EVENT_URL_DATA = 0;
34int ECORE_CON_EVENT_URL_COMPLETE = 0; 36int ECORE_CON_EVENT_URL_COMPLETE = 0;
35int ECORE_CON_EVENT_URL_PROGRESS = 0; 37int ECORE_CON_EVENT_URL_PROGRESS = 0;
36 38
37#ifdef HAVE_CURL 39#ifdef HAVE_CURL
40static void _ecore_con_url_event_url_complete(Ecore_Con_Url *url_con, CURLMsg *curlmsg);
41static void _ecore_con_url_multi_remove(Ecore_Con_Url *url_con);
38static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con); 42static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con);
39static size_t _ecore_con_url_header_cb(void *ptr, 43static size_t _ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream);
40 size_t size, 44static size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp);
41 size_t nitems, 45static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
42 void *stream); 46static size_t _ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream);
43static size_t _ecore_con_url_data_cb(void *buffer, 47static void _ecore_con_event_url_free(Ecore_Con_Url *url_con, void *ev);
44 size_t size, 48static Eina_Bool _ecore_con_url_timer(void *data);
45 size_t nitems, 49static Eina_Bool _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
46 void *userp);
47static int _ecore_con_url_progress_cb(void *clientp,
48 double dltotal,
49 double dlnow,
50 double ultotal,
51 double ulnow);
52static size_t _ecore_con_url_read_cb(void *ptr,
53 size_t size,
54 size_t nitems,
55 void *stream);
56static void _ecore_con_event_url_free(void *data __UNUSED__,
57 void *ev);
58static Eina_Bool _ecore_con_url_idler_handler(void *data);
59static Eina_Bool _ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__);
60static Eina_Bool _ecore_con_url_timeout_cb(void *data); 50static Eina_Bool _ecore_con_url_timeout_cb(void *data);
51static void _ecore_con_url_status_get(Ecore_Con_Url *url_con);
61 52
62static Eina_List *_url_con_list = NULL; 53static Eina_List *_url_con_list = NULL;
63static Eina_List *_fd_hd_list = NULL; 54static Eina_List *_fd_hd_list = NULL;
64static CURLM *_curlm = NULL; 55static CURLM *_curlm = NULL;
65static fd_set _current_fd_set;
66static int _init_count = 0; 56static int _init_count = 0;
67static Ecore_Timer *_curl_timeout = NULL; 57static Ecore_Timer *_curl_timer = NULL;
68static Eina_Bool pipelining = EINA_FALSE; 58static Eina_Bool pipelining = EINA_FALSE;
69 59
70#endif 60#endif
@@ -79,28 +69,28 @@ EAPI int
79ecore_con_url_init(void) 69ecore_con_url_init(void)
80{ 70{
81#ifdef HAVE_CURL 71#ifdef HAVE_CURL
72 long ms;
82 if (++_init_count > 1) return _init_count; 73 if (++_init_count > 1) return _init_count;
83 74
84 if (!ECORE_CON_EVENT_URL_DATA) ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); 75 ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
85 if (!ECORE_CON_EVENT_URL_COMPLETE) ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); 76 ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
86 if (!ECORE_CON_EVENT_URL_PROGRESS) ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new(); 77 ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new();
78
79 // curl_global_init() is not thread safe!
80 if (curl_global_init(CURL_GLOBAL_ALL)) return --_init_count;
87 81
82 _curlm = curl_multi_init();
88 if (!_curlm) 83 if (!_curlm)
89 { 84 {
90 long ms; 85 curl_global_cleanup();
91 86 return --_init_count;
92 // curl_global_init() is not thread safe! 87 }
93 if (curl_global_init(CURL_GLOBAL_ALL)) return --_init_count;
94
95 _curlm = curl_multi_init();
96 if (!_curlm) return --_init_count;
97 88
98 curl_multi_timeout(_curlm, &ms); 89 curl_multi_timeout(_curlm, &ms);
99 if (ms <= 0) ms = 100; 90 if (ms >= CURL_MIN_TIMEOUT || ms <= 0) ms = CURL_MIN_TIMEOUT;
100 91
101 _curl_timeout = ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler, (void *)0xACE); 92 _curl_timer = ecore_timer_add((double)ms / 1000, _ecore_con_url_timer, NULL);
102 ecore_timer_freeze(_curl_timeout); 93 ecore_timer_freeze(_curl_timer);
103 }
104 94
105 return _init_count; 95 return _init_count;
106#else 96#else
@@ -112,31 +102,30 @@ EAPI int
112ecore_con_url_shutdown(void) 102ecore_con_url_shutdown(void)
113{ 103{
114#ifdef HAVE_CURL 104#ifdef HAVE_CURL
105 Ecore_Con_Url *url_con;
106 Ecore_Fd_Handler *fd_handler;
115 if (_init_count == 0) return 0; 107 if (_init_count == 0) return 0;
108 --_init_count;
109 if (_init_count) return _init_count;
116 110
117 if (--_init_count == 0) 111 if (_curl_timer)
118 { 112 {
119 Ecore_Con_Url *con_url; 113 ecore_timer_del(_curl_timer);
120 Ecore_Fd_Handler *fd_handler; 114 _curl_timer = NULL;
121 115 }
122 if (_curl_timeout)
123 {
124 ecore_timer_del(_curl_timeout);
125 _curl_timeout = NULL;
126 }
127 116
128 FD_ZERO(&_current_fd_set); 117 EINA_LIST_FREE(_url_con_list, url_con)
129 EINA_LIST_FREE(_url_con_list, con_url) ecore_con_url_free(con_url); 118 ecore_con_url_free(url_con);
130 EINA_LIST_FREE(_fd_hd_list, fd_handler) ecore_main_fd_handler_del(fd_handler); 119 EINA_LIST_FREE(_fd_hd_list, fd_handler)
120 ecore_main_fd_handler_del(fd_handler);
131 121
132 if (_curlm) 122 if (_curlm)
133 { 123 {
134 curl_multi_cleanup(_curlm); 124 curl_multi_cleanup(_curlm);
135 _curlm = NULL; 125 _curlm = NULL;
136 } 126 }
137 curl_global_cleanup(); 127 curl_global_cleanup();
138 } 128 return 0;
139 return _init_count;
140#endif 129#endif
141 return 1; 130 return 1;
142} 131}
@@ -145,14 +134,12 @@ EAPI void
145ecore_con_url_pipeline_set(Eina_Bool enable) 134ecore_con_url_pipeline_set(Eina_Bool enable)
146{ 135{
147#ifdef HAVE_CURL 136#ifdef HAVE_CURL
148 if (enable) 137 if (enable == pipelining) return;
149 curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, 1); 138 curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, !!enable);
150 else 139 pipelining = enable;
151 curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, 0);
152 pipelining = enable;
153#else 140#else
154 return; 141 return;
155 (void)enable; 142 (void)enable;
156#endif 143#endif
157} 144}
158 145
@@ -160,11 +147,13 @@ EAPI Eina_Bool
160ecore_con_url_pipeline_get(void) 147ecore_con_url_pipeline_get(void)
161{ 148{
162#ifdef HAVE_CURL 149#ifdef HAVE_CURL
163 return pipelining; 150 return pipelining;
164#endif 151#endif
165 return EINA_FALSE; 152 return EINA_FALSE;
166} 153}
167 154
155extern Ecore_Con_Socks *_ecore_con_proxy_global;
156
168EAPI Ecore_Con_Url * 157EAPI Ecore_Con_Url *
169ecore_con_url_new(const char *url) 158ecore_con_url_new(const char *url)
170{ 159{
@@ -196,22 +185,41 @@ ecore_con_url_new(const char *url)
196 return NULL; 185 return NULL;
197 } 186 }
198 187
188 // Read socks proxy
199 url_con->proxy_type = -1; 189 url_con->proxy_type = -1;
200 if (_ecore_con_proxy_global) 190 if (_ecore_con_proxy_global && _ecore_con_proxy_global->ip &&
191 (_ecore_con_proxy_global->version == 4 ||
192 _ecore_con_proxy_global->version == 5))
201 { 193 {
202 if (_ecore_con_proxy_global->ip) 194 char proxy[256];
195 char host[256];
196
197 if (_ecore_con_proxy_global->version == 5)
203 { 198 {
204 char host[128]; 199 if (_ecore_con_proxy_global->lookup)
205 if (_ecore_con_proxy_global->port > 0 && 200 snprintf(host, sizeof(host), "socks5h://%s",
206 _ecore_con_proxy_global->port <= 65535) 201 _ecore_con_proxy_global->ip);
207 snprintf(host, sizeof(host), "socks4://%s:%d", 202 else snprintf(host, sizeof(host), "socks5://%s",
208 _ecore_con_proxy_global->ip, 203 _ecore_con_proxy_global->ip);
209 _ecore_con_proxy_global->port); 204 }
210 else 205 else if (_ecore_con_proxy_global->version == 4)
211 snprintf(host, sizeof(host), "socks4://%s", 206 {
207 if (_ecore_con_proxy_global->lookup)
208 snprintf(host, sizeof(host), "socks4a://%s",
212 _ecore_con_proxy_global->ip); 209 _ecore_con_proxy_global->ip);
213 ecore_con_url_proxy_set(url_con, host); 210 else snprintf(host, sizeof(host), "socks4://%s",
211 _ecore_con_proxy_global->ip);
214 } 212 }
213
214 if (_ecore_con_proxy_global->port > 0 &&
215 _ecore_con_proxy_global->port <= 65535)
216 snprintf(proxy, sizeof(proxy), "%s:%d", host,
217 _ecore_con_proxy_global->port);
218 else snprintf(proxy, sizeof(proxy), "%s", host);
219
220 ecore_con_url_proxy_set(url_con, proxy);
221 ecore_con_url_proxy_username_set(url_con,
222 _ecore_con_proxy_global->username);
215 } 223 }
216 224
217 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate"); 225 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate");
@@ -291,10 +299,8 @@ ecore_con_url_free(Ecore_Con_Url *url_con)
291{ 299{
292#ifdef HAVE_CURL 300#ifdef HAVE_CURL
293 char *s; 301 char *s;
294 CURLMcode ret;
295 302
296 if (!url_con) 303 if (!url_con) return;
297 return;
298 304
299 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 305 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
300 { 306 {
@@ -302,17 +308,16 @@ ecore_con_url_free(Ecore_Con_Url *url_con)
302 return; 308 return;
303 } 309 }
304 310
305 ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
306
307 if (url_con->curl_easy) 311 if (url_con->curl_easy)
308 { 312 {
313 // FIXME : How can we delete curl_easy's fds ?? (Curl do not give this info.)
314 // This cause "Failed to delete epoll fd xx!" error messages
309 curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL); 315 curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL);
310 curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE); 316 curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE);
311 317
312 if (eina_list_data_find(_url_con_list, url_con)) 318 if (url_con->multi)
313 { 319 {
314 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); 320 _ecore_con_url_multi_remove(url_con);
315 if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
316 _url_con_list = eina_list_remove(_url_con_list, url_con); 321 _url_con_list = eina_list_remove(_url_con_list, url_con);
317 } 322 }
318 323
@@ -320,6 +325,12 @@ ecore_con_url_free(Ecore_Con_Url *url_con)
320 } 325 }
321 if (url_con->timer) ecore_timer_del(url_con->timer); 326 if (url_con->timer) ecore_timer_del(url_con->timer);
322 327
328 url_con->curl_easy = NULL;
329 url_con->timer = NULL;
330 url_con->dead = EINA_TRUE;
331 if (url_con->event_count) return;
332 ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
333
323 curl_slist_free_all(url_con->headers); 334 curl_slist_free_all(url_con->headers);
324 EINA_LIST_FREE(url_con->additional_headers, s) 335 EINA_LIST_FREE(url_con->additional_headers, s)
325 free(s); 336 free(s);
@@ -350,9 +361,27 @@ ecore_con_url_url_get(Ecore_Con_Url *url_con)
350#endif 361#endif
351} 362}
352 363
364EAPI int
365ecore_con_url_status_code_get(Ecore_Con_Url *url_con)
366{
367#ifdef HAVE_CURL
368 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
369 {
370 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, __func__);
371 return 0;
372 }
373
374 if (url_con->status) return url_con->status;
375 _ecore_con_url_status_get(url_con);
376 return url_con->status;
377#else
378 return -1;
379 (void)url_con;
380#endif
381}
382
353EAPI Eina_Bool 383EAPI Eina_Bool
354ecore_con_url_url_set(Ecore_Con_Url *url_con, 384ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url)
355 const char *url)
356{ 385{
357#ifdef HAVE_CURL 386#ifdef HAVE_CURL
358 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 387 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -361,8 +390,7 @@ ecore_con_url_url_set(Ecore_Con_Url *url_con,
361 return EINA_FALSE; 390 return EINA_FALSE;
362 } 391 }
363 392
364 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; 393 if (url_con->dead) return EINA_FALSE;
365
366 eina_stringshare_replace(&url_con->url, url); 394 eina_stringshare_replace(&url_con->url, url);
367 395
368 if (url_con->url) 396 if (url_con->url)
@@ -380,8 +408,7 @@ ecore_con_url_url_set(Ecore_Con_Url *url_con,
380} 408}
381 409
382EAPI void 410EAPI void
383ecore_con_url_data_set(Ecore_Con_Url *url_con, 411ecore_con_url_data_set(Ecore_Con_Url *url_con, void *data)
384 void *data)
385{ 412{
386#ifdef HAVE_CURL 413#ifdef HAVE_CURL
387 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 414 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -399,13 +426,12 @@ ecore_con_url_data_set(Ecore_Con_Url *url_con,
399} 426}
400 427
401EAPI void 428EAPI void
402ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, 429ecore_con_url_additional_header_add(Ecore_Con_Url *url_con, const char *key, const char *value)
403 const char *key,
404 const char *value)
405{ 430{
406#ifdef HAVE_CURL 431#ifdef HAVE_CURL
407 char *tmp; 432 char *tmp;
408 433
434 if (url_con->dead) return;
409 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 435 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
410 { 436 {
411 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, 437 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
@@ -413,6 +439,7 @@ ecore_con_url_additional_header_add(Ecore_Con_Url *url_con,
413 return; 439 return;
414 } 440 }
415 441
442 if (url_con->dead) return;
416 tmp = malloc(strlen(key) + strlen(value) + 3); 443 tmp = malloc(strlen(key) + strlen(value) + 3);
417 if (!tmp) 444 if (!tmp)
418 return; 445 return;
@@ -467,9 +494,7 @@ ecore_con_url_data_get(Ecore_Con_Url *url_con)
467} 494}
468 495
469EAPI void 496EAPI void
470ecore_con_url_time(Ecore_Con_Url *url_con, 497ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, double timestamp)
471 Ecore_Con_Url_Time condition,
472 double timestamp)
473{ 498{
474#ifdef HAVE_CURL 499#ifdef HAVE_CURL
475 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 500 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -478,6 +503,7 @@ ecore_con_url_time(Ecore_Con_Url *url_con,
478 return; 503 return;
479 } 504 }
480 505
506 if (url_con->dead) return;
481 url_con->time_condition = condition; 507 url_con->time_condition = condition;
482 url_con->timestamp = timestamp; 508 url_con->timestamp = timestamp;
483#else 509#else
@@ -489,8 +515,7 @@ ecore_con_url_time(Ecore_Con_Url *url_con,
489} 515}
490 516
491EAPI void 517EAPI void
492ecore_con_url_fd_set(Ecore_Con_Url *url_con, 518ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd)
493 int fd)
494{ 519{
495#ifdef HAVE_CURL 520#ifdef HAVE_CURL
496 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 521 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -499,6 +524,7 @@ ecore_con_url_fd_set(Ecore_Con_Url *url_con,
499 return; 524 return;
500 } 525 }
501 526
527 if (url_con->dead) return;
502 url_con->write_fd = fd; 528 url_con->write_fd = fd;
503#else 529#else
504 return; 530 return;
@@ -537,10 +563,7 @@ ecore_con_url_response_headers_get(Ecore_Con_Url *url_con)
537} 563}
538 564
539EAPI Eina_Bool 565EAPI Eina_Bool
540ecore_con_url_httpauth_set(Ecore_Con_Url *url_con, 566ecore_con_url_httpauth_set(Ecore_Con_Url *url_con, const char *username, const char *password, Eina_Bool safe)
541 const char *username,
542 const char *password,
543 Eina_Bool safe)
544{ 567{
545#ifdef HAVE_CURL 568#ifdef HAVE_CURL
546 CURLcode ret; 569 CURLcode ret;
@@ -552,6 +575,7 @@ ecore_con_url_httpauth_set(Ecore_Con_Url *url_con,
552 return EINA_FALSE; 575 return EINA_FALSE;
553 } 576 }
554 577
578 if (url_con->dead) return EINA_FALSE;
555# if LIBCURL_VERSION_NUM >= 0x071301 579# if LIBCURL_VERSION_NUM >= 0x071301
556 if ((username) && (password)) 580 if ((username) && (password))
557 { 581 {
@@ -596,11 +620,7 @@ ecore_con_url_httpauth_set(Ecore_Con_Url *url_con,
596#define MODE_POST 2 620#define MODE_POST 2
597 621
598static Eina_Bool 622static Eina_Bool
599_ecore_con_url_send(Ecore_Con_Url *url_con, 623_ecore_con_url_send(Ecore_Con_Url *url_con, int mode, const void *data, long length, const char *content_type)
600 int mode,
601 const void *data,
602 long length,
603 const char *content_type)
604{ 624{
605#ifdef HAVE_CURL 625#ifdef HAVE_CURL
606 Eina_List *l; 626 Eina_List *l;
@@ -613,15 +633,14 @@ _ecore_con_url_send(Ecore_Con_Url *url_con,
613 return EINA_FALSE; 633 return EINA_FALSE;
614 } 634 }
615 635
616 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; 636 if (!url_con->url) return EINA_FALSE;
617 637 if (url_con->dead) return EINA_FALSE;
618 if (!url_con->url)
619 return EINA_FALSE;
620 638
621 /* Free response headers from previous send() calls */ 639 /* Free response headers from previous send() calls */
622 EINA_LIST_FREE(url_con->response_headers, s) 640 EINA_LIST_FREE(url_con->response_headers, s)
623 free((char *)s); 641 free((char *)s);
624 url_con->response_headers = NULL; 642 url_con->response_headers = NULL;
643 url_con->status = 0;
625 644
626 curl_slist_free_all(url_con->headers); 645 curl_slist_free_all(url_con->headers);
627 url_con->headers = NULL; 646 url_con->headers = NULL;
@@ -693,15 +712,6 @@ _ecore_con_url_send(Ecore_Con_Url *url_con,
693#endif 712#endif
694} 713}
695 714
696EINA_DEPRECATED EAPI Eina_Bool
697ecore_con_url_send(Ecore_Con_Url *url_con,
698 const void *data,
699 long length,
700 const char *content_type)
701{
702 return _ecore_con_url_send(url_con, MODE_AUTO, data, length, content_type);
703}
704
705EAPI Eina_Bool 715EAPI Eina_Bool
706ecore_con_url_get(Ecore_Con_Url *url_con) 716ecore_con_url_get(Ecore_Con_Url *url_con)
707{ 717{
@@ -709,20 +719,13 @@ ecore_con_url_get(Ecore_Con_Url *url_con)
709} 719}
710 720
711EAPI Eina_Bool 721EAPI Eina_Bool
712ecore_con_url_post(Ecore_Con_Url *url_con, 722ecore_con_url_post(Ecore_Con_Url *url_con, const void *data, long length, const char *content_type)
713 const void *data,
714 long length,
715 const char *content_type)
716{ 723{
717 return _ecore_con_url_send(url_con, MODE_POST, data, length, content_type); 724 return _ecore_con_url_send(url_con, MODE_POST, data, length, content_type);
718} 725}
719 726
720EAPI Eina_Bool 727EAPI Eina_Bool
721ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, 728ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, const char *filename, const char *user, const char *pass, const char *upload_dir)
722 const char *filename,
723 const char *user,
724 const char *pass,
725 const char *upload_dir)
726{ 729{
727#ifdef HAVE_CURL 730#ifdef HAVE_CURL
728 char url[4096]; 731 char url[4096];
@@ -739,54 +742,50 @@ ecore_con_url_ftp_upload(Ecore_Con_Url *url_con,
739 return EINA_FALSE; 742 return EINA_FALSE;
740 } 743 }
741 744
742 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; 745 if (url_con->dead) return EINA_FALSE;
746 if (!url_con->url) return EINA_FALSE;
747 if ((!filename) || (!filename[0])) return EINA_FALSE;
743 748
744 if (!url_con->url) 749 if (stat(filename, &file_info))
745 return EINA_FALSE; 750 return EINA_FALSE;
746 751
747 if (filename) 752 snprintf(userpwd, sizeof(userpwd), "%s:%s", user, pass);
753 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERPWD, userpwd);
754 if (ret != CURLE_OK)
748 { 755 {
749 if (stat(filename, &file_info)) 756 ERR("Could not set username and password for FTP upload: %s",
750 return EINA_FALSE; 757 curl_easy_strerror(ret));
751 758 return EINA_FALSE;
752 snprintf(userpwd, sizeof(userpwd), "%s:%s", user, pass); 759 }
753 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERPWD, userpwd);
754 if (ret != CURLE_OK)
755 {
756 ERR("Could not set username and password for FTP upload: %s",
757 curl_easy_strerror(ret));
758 return EINA_FALSE;
759 }
760 760
761 char tmp[PATH_MAX]; 761 char tmp[PATH_MAX];
762 snprintf(tmp, PATH_MAX, "%s", filename); 762 snprintf(tmp, PATH_MAX, "%s", filename);
763 763
764 if (upload_dir) 764 if (upload_dir)
765 snprintf(url, sizeof(url), "ftp://%s/%s/%s", url_con->url, 765 snprintf(url, sizeof(url), "ftp://%s/%s/%s", url_con->url,
766 upload_dir, basename(tmp)); 766 upload_dir, basename(tmp));
767 else 767 else
768 snprintf(url, sizeof(url), "ftp://%s/%s", url_con->url, 768 snprintf(url, sizeof(url), "ftp://%s/%s", url_con->url,
769 basename(tmp)); 769 basename(tmp));
770 770
771 if (!ecore_con_url_url_set(url_con, url)) 771 if (!ecore_con_url_url_set(url_con, url))
772 return EINA_FALSE; 772 return EINA_FALSE;
773 773
774 curl_easy_setopt(url_con->curl_easy, CURLOPT_INFILESIZE_LARGE, 774 curl_easy_setopt(url_con->curl_easy, CURLOPT_INFILESIZE_LARGE,
775 (curl_off_t)file_info.st_size); 775 (curl_off_t)file_info.st_size);
776 curl_easy_setopt(url_con->curl_easy, CURLOPT_UPLOAD, 1); 776 curl_easy_setopt(url_con->curl_easy, CURLOPT_UPLOAD, 1);
777 curl_easy_setopt(url_con->curl_easy, CURLOPT_READFUNCTION, 777 curl_easy_setopt(url_con->curl_easy, CURLOPT_READFUNCTION,
778 _ecore_con_url_read_cb); 778 _ecore_con_url_read_cb);
779 779
780 fd = fopen(filename, "rb"); 780 fd = fopen(filename, "rb");
781 if (!fd) 781 if (!fd)
782 { 782 {
783 ERR("Could not open \"%s\" for FTP upload", filename); 783 ERR("Could not open \"%s\" for FTP upload", filename);
784 return EINA_FALSE; 784 return EINA_FALSE;
785 }
786 curl_easy_setopt(url_con->curl_easy, CURLOPT_READDATA, fd);
787
788 return _ecore_con_url_perform(url_con);
789 } 785 }
786 curl_easy_setopt(url_con->curl_easy, CURLOPT_READDATA, fd);
787
788 return _ecore_con_url_perform(url_con);
790#else 789#else
791 return EINA_FALSE; 790 return EINA_FALSE;
792 (void)url_con; 791 (void)url_con;
@@ -795,8 +794,6 @@ ecore_con_url_ftp_upload(Ecore_Con_Url *url_con,
795 (void)pass; 794 (void)pass;
796 (void)upload_dir; 795 (void)upload_dir;
797#endif 796#endif
798
799 return EINA_FALSE;
800} 797}
801 798
802EAPI void 799EAPI void
@@ -813,6 +810,7 @@ ecore_con_url_cookies_init(Ecore_Con_Url *url_con)
813 return; 810 return;
814 } 811 }
815 812
813 if (url_con->dead) return;
816 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, ""); 814 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, "");
817#else 815#else
818 return; 816 return;
@@ -834,6 +832,7 @@ ecore_con_url_cookies_ignore_old_session_set(Ecore_Con_Url *url_con, Eina_Bool i
834 return; 832 return;
835 } 833 }
836 834
835 if (url_con->dead) return;
837 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIESESSION, ignore); 836 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIESESSION, ignore);
838#else 837#else
839 return; 838 return;
@@ -856,6 +855,7 @@ ecore_con_url_cookies_clear(Ecore_Con_Url *url_con)
856 return; 855 return;
857 } 856 }
858 857
858 if (url_con->dead) return;
859 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "ALL"); 859 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "ALL");
860#else 860#else
861 return; 861 return;
@@ -877,6 +877,7 @@ ecore_con_url_cookies_session_clear(Ecore_Con_Url *url_con)
877 return; 877 return;
878 } 878 }
879 879
880 if (url_con->dead) return;
880 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "SESS"); 881 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "SESS");
881#else 882#else
882 return; 883 return;
@@ -885,7 +886,7 @@ ecore_con_url_cookies_session_clear(Ecore_Con_Url *url_con)
885} 886}
886 887
887EAPI void 888EAPI void
888ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char * const file_name) 889ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char *const file_name)
889{ 890{
890#ifdef HAVE_CURL 891#ifdef HAVE_CURL
891 if (!url_con) 892 if (!url_con)
@@ -898,6 +899,7 @@ ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char * const file_n
898 return; 899 return;
899 } 900 }
900 901
902 if (url_con->dead) return;
901 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, file_name); 903 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, file_name);
902#else 904#else
903 return; 905 return;
@@ -907,7 +909,7 @@ ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char * const file_n
907} 909}
908 910
909EAPI Eina_Bool 911EAPI Eina_Bool
910ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con, const char * const cookiejar_file) 912ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con, const char *const cookiejar_file)
911{ 913{
912#ifdef HAVE_CURL 914#ifdef HAVE_CURL
913 CURLcode ret; 915 CURLcode ret;
@@ -922,6 +924,7 @@ ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con, const char * const co
922 return EINA_FALSE; 924 return EINA_FALSE;
923 } 925 }
924 926
927 if (url_con->dead) return EINA_FALSE;
925 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEJAR, 928 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEJAR,
926 cookiejar_file); 929 cookiejar_file);
927 if (ret != CURLE_OK) 930 if (ret != CURLE_OK)
@@ -953,6 +956,7 @@ ecore_con_url_cookies_jar_write(Ecore_Con_Url *url_con)
953 return; 956 return;
954 } 957 }
955 958
959 if (url_con->dead) return;
956 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "FLUSH"); 960 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "FLUSH");
957#else 961#else
958 return; 962 return;
@@ -961,8 +965,7 @@ ecore_con_url_cookies_jar_write(Ecore_Con_Url *url_con)
961} 965}
962 966
963EAPI void 967EAPI void
964ecore_con_url_verbose_set(Ecore_Con_Url *url_con, 968ecore_con_url_verbose_set(Ecore_Con_Url *url_con, Eina_Bool verbose)
965 Eina_Bool verbose)
966{ 969{
967#ifdef HAVE_CURL 970#ifdef HAVE_CURL
968 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 971 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -972,11 +975,10 @@ ecore_con_url_verbose_set(Ecore_Con_Url *url_con,
972 return; 975 return;
973 } 976 }
974 977
975 if (eina_list_data_find(_url_con_list, url_con)) return;
976
977 if (!url_con->url) 978 if (!url_con->url)
978 return; 979 return;
979 980
981 if (url_con->dead) return;
980 curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, (int)verbose); 982 curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, (int)verbose);
981#else 983#else
982 return; 984 return;
@@ -986,8 +988,7 @@ ecore_con_url_verbose_set(Ecore_Con_Url *url_con,
986} 988}
987 989
988EAPI void 990EAPI void
989ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, 991ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, Eina_Bool use_epsv)
990 Eina_Bool use_epsv)
991{ 992{
992#ifdef HAVE_CURL 993#ifdef HAVE_CURL
993 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 994 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -997,11 +998,10 @@ ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con,
997 return; 998 return;
998 } 999 }
999 1000
1000 if (eina_list_data_find(_url_con_list, url_con)) return;
1001
1002 if (!url_con->url) 1001 if (!url_con->url)
1003 return; 1002 return;
1004 1003
1004 if (url_con->dead) return;
1005 curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, (int)use_epsv); 1005 curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, (int)use_epsv);
1006#else 1006#else
1007 return; 1007 return;
@@ -1023,8 +1023,7 @@ ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con,
1023 * @since 1.1.0 1023 * @since 1.1.0
1024 */ 1024 */
1025EAPI void 1025EAPI void
1026ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con, 1026ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con, Eina_Bool verify)
1027 Eina_Bool verify)
1028{ 1027{
1029#ifdef HAVE_CURL 1028#ifdef HAVE_CURL
1030 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 1029 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
@@ -1034,11 +1033,10 @@ ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con,
1034 return; 1033 return;
1035 } 1034 }
1036 1035
1037 if (eina_list_data_find(_url_con_list, url_con)) return;
1038
1039 if (!url_con->url) 1036 if (!url_con->url)
1040 return; 1037 return;
1041 1038
1039 if (url_con->dead) return;
1042 curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, (int)verify); 1040 curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, (int)verify);
1043#else 1041#else
1044 return; 1042 return;
@@ -1073,19 +1071,19 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path)
1073#ifdef HAVE_CURL 1071#ifdef HAVE_CURL
1074 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) 1072 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1075 { 1073 {
1076 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ssl_ca_set"); 1074 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ssl_ca_set");
1077 return -1; 1075 return -1;
1078 } 1076 }
1079 1077
1080 if (eina_list_data_find(_url_con_list, url_con)) return -1;
1081 if (!url_con->url) return -1; 1078 if (!url_con->url) return -1;
1079 if (url_con->dead) return -1;
1082 if (ca_path == NULL) 1080 if (ca_path == NULL)
1083 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0); 1081 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0);
1084 else 1082 else
1085 { 1083 {
1086 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 1); 1084 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 1);
1087 if (!res) 1085 if (!res)
1088 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_CAINFO, ca_path); 1086 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_CAINFO, ca_path);
1089 } 1087 }
1090#else 1088#else
1091 return -1; 1089 return -1;
@@ -1097,6 +1095,47 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path)
1097} 1095}
1098 1096
1099EAPI Eina_Bool 1097EAPI Eina_Bool
1098ecore_con_url_http_version_set(Ecore_Con_Url *url_con, Ecore_Con_Url_Http_Version version)
1099{
1100#ifdef HAVE_CURL
1101 int res = -1;
1102 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1103 {
1104 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_http_version_set");
1105 return EINA_FALSE;
1106 }
1107 if (url_con->dead) return EINA_FALSE;
1108 switch (version)
1109 {
1110 case ECORE_CON_URL_HTTP_VERSION_1_0:
1111 res = curl_easy_setopt(url_con->curl_easy,
1112 CURLOPT_HTTP_VERSION,
1113 CURL_HTTP_VERSION_1_0);
1114 break;
1115
1116 case ECORE_CON_URL_HTTP_VERSION_1_1:
1117 res = curl_easy_setopt(url_con->curl_easy,
1118 CURLOPT_HTTP_VERSION,
1119 CURL_HTTP_VERSION_1_1);
1120 break;
1121
1122 default:
1123 break;
1124 }
1125 if (res != CURLE_OK)
1126 {
1127 ERR("curl http version setting failed: %s", curl_easy_strerror(res));
1128 return EINA_FALSE;
1129 }
1130 return EINA_TRUE;
1131#else
1132 (void)url_con;
1133 (void)version;
1134 return EINA_FALSE;
1135#endif
1136}
1137
1138EAPI Eina_Bool
1100ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy) 1139ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy)
1101{ 1140{
1102#ifdef HAVE_CURL 1141#ifdef HAVE_CURL
@@ -1109,8 +1148,8 @@ ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy)
1109 return EINA_FALSE; 1148 return EINA_FALSE;
1110 } 1149 }
1111 1150
1112 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE;
1113 if (!url_con->url) return EINA_FALSE; 1151 if (!url_con->url) return EINA_FALSE;
1152 if (url_con->dead) return EINA_FALSE;
1114 1153
1115 if (!proxy) res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, ""); 1154 if (!proxy) res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, "");
1116 else 1155 else
@@ -1121,14 +1160,20 @@ ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy)
1121 if (vers->version_num < 0x71507) 1160 if (vers->version_num < 0x71507)
1122 { 1161 {
1123 url_con->proxy_type = CURLPROXY_HTTP; 1162 url_con->proxy_type = CURLPROXY_HTTP;
1124 if (strstr(proxy, "socks4")) url_con->proxy_type = CURLPROXY_SOCKS4; 1163 if (strstr(proxy, "socks4a"))
1125 else if (strstr(proxy, "socks4a")) url_con->proxy_type = CURLPROXY_SOCKS4A; 1164 url_con->proxy_type = CURLPROXY_SOCKS4A;
1126 else if (strstr(proxy, "socks5")) url_con->proxy_type = CURLPROXY_SOCKS5; 1165 else if (strstr(proxy, "socks4"))
1127 else if (strstr(proxy, "socks5h")) url_con->proxy_type = CURLPROXY_SOCKS5_HOSTNAME; 1166 url_con->proxy_type = CURLPROXY_SOCKS4;
1128 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXYTYPE, url_con->proxy_type); 1167 else if (strstr(proxy, "socks5h"))
1168 url_con->proxy_type = CURLPROXY_SOCKS5_HOSTNAME;
1169 else if (strstr(proxy, "socks5"))
1170 url_con->proxy_type = CURLPROXY_SOCKS5;
1171 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXYTYPE,
1172 url_con->proxy_type);
1129 if (res != CURLE_OK) 1173 if (res != CURLE_OK)
1130 { 1174 {
1131 ERR("curl proxy type setting failed: %s", curl_easy_strerror(res)); 1175 ERR("curl proxy type setting failed: %s",
1176 curl_easy_strerror(res));
1132 url_con->proxy_type = -1; 1177 url_con->proxy_type = -1;
1133 return EINA_FALSE; 1178 return EINA_FALSE;
1134 } 1179 }
@@ -1159,7 +1204,7 @@ ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout)
1159 return; 1204 return;
1160 } 1205 }
1161 1206
1162 if (eina_list_data_find(_url_con_list, url_con)) return; 1207 if (url_con->dead) return;
1163 if (!url_con->url || timeout < 0) return; 1208 if (!url_con->url || timeout < 0) return;
1164 if (url_con->timer) ecore_timer_del(url_con->timer); 1209 if (url_con->timer) ecore_timer_del(url_con->timer);
1165 url_con->timer = ecore_timer_add(timeout, _ecore_con_url_timeout_cb, url_con); 1210 url_con->timer = ecore_timer_add(timeout, _ecore_con_url_timeout_cb, url_con);
@@ -1181,9 +1226,9 @@ ecore_con_url_proxy_username_set(Ecore_Con_Url *url_con, const char *username)
1181 return EINA_FALSE; 1226 return EINA_FALSE;
1182 } 1227 }
1183 1228
1184 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; 1229 if (url_con->dead) return EINA_FALSE;
1185 if (!url_con->url) return EINA_FALSE; 1230 if (!url_con->url) return EINA_FALSE;
1186 if (!username) return EINA_FALSE; 1231 if ((!username) || (!username[0])) return EINA_FALSE;
1187 if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) 1232 if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A)
1188 { 1233 {
1189 ERR("Proxy type should be socks5 and above"); 1234 ERR("Proxy type should be socks5 and above");
@@ -1214,8 +1259,8 @@ ecore_con_url_proxy_password_set(Ecore_Con_Url *url_con, const char *password)
1214 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_password_set"); 1259 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_password_set");
1215 return EINA_FALSE; 1260 return EINA_FALSE;
1216 } 1261 }
1217 if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE;
1218 if (!url_con->url) return EINA_FALSE; 1262 if (!url_con->url) return EINA_FALSE;
1263 if (url_con->dead) return EINA_FALSE;
1219 if (!password) return EINA_FALSE; 1264 if (!password) return EINA_FALSE;
1220 if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) 1265 if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A)
1221 { 1266 {
@@ -1242,19 +1287,61 @@ ecore_con_url_proxy_password_set(Ecore_Con_Url *url_con, const char *password)
1242 */ 1287 */
1243 1288
1244#ifdef HAVE_CURL 1289#ifdef HAVE_CURL
1290static void
1291_ecore_con_url_status_get(Ecore_Con_Url *url_con)
1292{
1293 long status = 0;
1294
1295 if (!url_con->curl_easy) return;
1296 if (!curl_easy_getinfo(url_con->curl_easy, CURLINFO_RESPONSE_CODE, &status))
1297 url_con->status = status;
1298 else
1299 url_con->status = 0;
1300}
1301
1302static void
1303_ecore_con_url_event_url_complete(Ecore_Con_Url *url_con, CURLMsg *curlmsg)
1304{
1305 Ecore_Con_Event_Url_Complete *e;
1306
1307 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
1308 if (!e) return;
1309
1310 if (curlmsg && (curlmsg->data.result == CURLE_OK))
1311 {
1312 if (!url_con->status)
1313 _ecore_con_url_status_get(url_con);
1314 }
1315 else if (curlmsg)
1316 ERR("Curl message have errors: %d", curlmsg->data.result);
1317 else
1318 CRIT("THIS IS BAD.");
1319
1320 e->status = url_con->status;
1321 e->url_con = url_con;
1322 url_con->event_count++;
1323 ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con);
1324}
1325
1326static void
1327_ecore_con_url_multi_remove(Ecore_Con_Url *url_con)
1328{
1329 CURLMcode ret;
1330
1331 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
1332 url_con->multi = EINA_FALSE;
1333 if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
1334}
1335
1245static Eina_Bool 1336static Eina_Bool
1246_ecore_con_url_timeout_cb(void *data) 1337_ecore_con_url_timeout_cb(void *data)
1247{ 1338{
1248 Ecore_Con_Url *url_con = data; 1339 Ecore_Con_Url *url_con = data;
1249 CURLMcode ret;
1250 Ecore_Con_Event_Url_Complete *e;
1251 1340
1252 if (!url_con) return ECORE_CALLBACK_CANCEL; 1341 if (!url_con) return ECORE_CALLBACK_CANCEL;
1253 if (!url_con->curl_easy) return ECORE_CALLBACK_CANCEL; 1342 if (!url_con->curl_easy) return ECORE_CALLBACK_CANCEL;
1254 if (!eina_list_data_find(_url_con_list, url_con)) return ECORE_CALLBACK_CANCEL;
1255 1343
1256 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); 1344 _ecore_con_url_multi_remove(url_con);
1257 if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
1258 _url_con_list = eina_list_remove(_url_con_list, url_con); 1345 _url_con_list = eina_list_remove(_url_con_list, url_con);
1259 1346
1260 curl_slist_free_all(url_con->headers); 1347 curl_slist_free_all(url_con->headers);
@@ -1262,21 +1349,12 @@ _ecore_con_url_timeout_cb(void *data)
1262 1349
1263 url_con->timer = NULL; 1350 url_con->timer = NULL;
1264 1351
1265 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); 1352 _ecore_con_url_event_url_complete(url_con, NULL);
1266 if (e)
1267 {
1268 e->url_con = url_con;
1269 e->status = 0;
1270 ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, _ecore_con_event_url_free, NULL);
1271 }
1272 return ECORE_CALLBACK_CANCEL; 1353 return ECORE_CALLBACK_CANCEL;
1273} 1354}
1274 1355
1275static size_t 1356static size_t
1276_ecore_con_url_data_cb(void *buffer, 1357_ecore_con_url_data_cb(void *buffer, size_t size, size_t nitems, void *userp)
1277 size_t size,
1278 size_t nitems,
1279 void *userp)
1280{ 1358{
1281 Ecore_Con_Url *url_con; 1359 Ecore_Con_Url *url_con;
1282 Ecore_Con_Event_Url_Data *e; 1360 Ecore_Con_Event_Url_Data *e;
@@ -1295,6 +1373,7 @@ _ecore_con_url_data_cb(void *buffer,
1295 1373
1296 url_con->received += real_size; 1374 url_con->received += real_size;
1297 1375
1376 INF("reading from %s", url_con->url);
1298 if (url_con->write_fd < 0) 1377 if (url_con->write_fd < 0)
1299 { 1378 {
1300 e = 1379 e =
@@ -1305,7 +1384,8 @@ _ecore_con_url_data_cb(void *buffer,
1305 e->url_con = url_con; 1384 e->url_con = url_con;
1306 e->size = real_size; 1385 e->size = real_size;
1307 memcpy(e->data, buffer, real_size); 1386 memcpy(e->data, buffer, real_size);
1308 ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, _ecore_con_event_url_free, NULL); 1387 url_con->event_count++;
1388 ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con);
1309 } 1389 }
1310 } 1390 }
1311 else 1391 else
@@ -1336,10 +1416,7 @@ _ecore_con_url_data_cb(void *buffer,
1336} 1416}
1337 1417
1338static size_t 1418static size_t
1339_ecore_con_url_header_cb(void *ptr, 1419_ecore_con_url_header_cb(void *ptr, size_t size, size_t nitems, void *stream)
1340 size_t size,
1341 size_t nitems,
1342 void *stream)
1343{ 1420{
1344 size_t real_size = size * nitems; 1421 size_t real_size = size * nitems;
1345 Ecore_Con_Url *url_con = stream; 1422 Ecore_Con_Url *url_con = stream;
@@ -1358,11 +1435,7 @@ _ecore_con_url_header_cb(void *ptr,
1358} 1435}
1359 1436
1360static int 1437static int
1361_ecore_con_url_progress_cb(void *clientp, 1438_ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
1362 double dltotal,
1363 double dlnow,
1364 double ultotal,
1365 double ulnow)
1366{ 1439{
1367 Ecore_Con_Event_Url_Progress *e; 1440 Ecore_Con_Event_Url_Progress *e;
1368 Ecore_Con_Url *url_con; 1441 Ecore_Con_Url *url_con;
@@ -1377,17 +1450,15 @@ _ecore_con_url_progress_cb(void *clientp,
1377 e->down.now = dlnow; 1450 e->down.now = dlnow;
1378 e->up.total = ultotal; 1451 e->up.total = ultotal;
1379 e->up.now = ulnow; 1452 e->up.now = ulnow;
1380 ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, _ecore_con_event_url_free, NULL); 1453 url_con->event_count++;
1454 ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, (Ecore_End_Cb)_ecore_con_event_url_free, url_con);
1381 } 1455 }
1382 1456
1383 return 0; 1457 return 0;
1384} 1458}
1385 1459
1386static size_t 1460static size_t
1387_ecore_con_url_read_cb(void *ptr, 1461_ecore_con_url_read_cb(void *ptr, size_t size, size_t nitems, void *stream)
1388 size_t size,
1389 size_t nitems,
1390 void *stream)
1391{ 1462{
1392 size_t retcode = fread(ptr, size, nitems, stream); 1463 size_t retcode = fread(ptr, size, nitems, stream);
1393 1464
@@ -1418,96 +1489,38 @@ _ecore_con_url_info_read(void)
1418 1489
1419 while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining))) 1490 while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining)))
1420 { 1491 {
1492 Eina_List *l, *ll;
1493 Ecore_Con_Url *url_con = NULL;
1494 DBG("Curl message: %d", curlmsg->msg);
1495
1421 if (curlmsg->msg == CURLMSG_DONE) 1496 if (curlmsg->msg == CURLMSG_DONE)
1422 { 1497 {
1423 Eina_List *l, *ll;
1424 Ecore_Con_Url *url_con;
1425
1426 EINA_LIST_FOREACH_SAFE(_url_con_list, l, ll, url_con) 1498 EINA_LIST_FOREACH_SAFE(_url_con_list, l, ll, url_con)
1427 { 1499 {
1428 if (curlmsg->easy_handle == url_con->curl_easy) 1500 if (curlmsg->easy_handle == url_con->curl_easy)
1429 { 1501 _ecore_con_url_event_url_complete(url_con, curlmsg);
1430 CURLMcode ret;
1431 Ecore_Con_Event_Url_Complete *e;
1432
1433 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
1434 if (e)
1435 {
1436 e->url_con = url_con;
1437 e->status = 0;
1438 if (curlmsg->data.result == CURLE_OK)
1439 {
1440 long status; /* curl API uses long, not int */
1441 status = 0;
1442 curl_easy_getinfo(curlmsg->easy_handle, CURLINFO_RESPONSE_CODE, &status);
1443 e->status = status;
1444 }
1445 ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, _ecore_con_event_url_free, NULL);
1446 }
1447
1448 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
1449 if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
1450 _url_con_list = eina_list_remove(_url_con_list, url_con);
1451 break;
1452 }
1453 } 1502 }
1454 } 1503 }
1455 } 1504 }
1456} 1505}
1457 1506
1458static void 1507static void
1459_ecore_con_url_curl_clear(void) 1508_ecore_con_url_curl_clear(void)
1460{ 1509{
1510 Ecore_Fd_Handler *fdh;
1461 Ecore_Con_Url *url_con; 1511 Ecore_Con_Url *url_con;
1462 1512
1463 FD_ZERO(&_current_fd_set); 1513 EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh);
1464 if (_fd_hd_list) 1514 EINA_LIST_FREE(_url_con_list, url_con) _ecore_con_url_multi_remove(url_con);
1465 {
1466 Ecore_Fd_Handler *fd_handler;
1467 EINA_LIST_FREE(_fd_hd_list, fd_handler)
1468 {
1469 int fd = ecore_main_fd_handler_fd_get(fd_handler);
1470 FD_CLR(fd, &_current_fd_set);
1471 // FIXME: ecore_main_fd_handler_del() sometimes give errors
1472 // because curl do not make fd itself controlled by users, but it can be ignored.
1473 ecore_main_fd_handler_del(fd_handler);
1474 }
1475 }
1476
1477 EINA_LIST_FREE(_url_con_list, url_con)
1478 {
1479 CURLMcode ret;
1480 Ecore_Con_Event_Url_Complete *e;
1481
1482 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
1483 if (e)
1484 {
1485 e->url_con = url_con;
1486 e->status = 0;
1487 ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, _ecore_con_event_url_free, NULL);
1488 }
1489 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
1490 if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret));
1491 }
1492} 1515}
1493 1516
1494static Eina_Bool 1517static Eina_Bool
1495_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) 1518_ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__)
1496{ 1519{
1497 if (_fd_hd_list) 1520 Ecore_Fd_Handler *fdh;
1498 { 1521 EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh);
1499 Ecore_Fd_Handler *fd_handler; 1522 ecore_timer_interval_set(_curl_timer, 0.1);
1500 EINA_LIST_FREE(_fd_hd_list, fd_handler) 1523 return ECORE_CALLBACK_CANCEL;
1501 {
1502 int fd = ecore_main_fd_handler_fd_get(fd_handler);
1503 FD_CLR(fd, &_current_fd_set);
1504 // FIXME: ecore_main_fd_handler_del() sometimes give errors
1505 // because curl do not make fd itself controlled by users, but it can be ignored.
1506 ecore_main_fd_handler_del(fd_handler);
1507 }
1508 }
1509 ecore_timer_thaw(_curl_timeout);
1510 return ECORE_CALLBACK_RENEW;
1511} 1524}
1512 1525
1513static void 1526static void
@@ -1516,7 +1529,6 @@ _ecore_con_url_fdset(void)
1516 CURLMcode ret; 1529 CURLMcode ret;
1517 fd_set read_set, write_set, exc_set; 1530 fd_set read_set, write_set, exc_set;
1518 int fd, fd_max; 1531 int fd, fd_max;
1519 Ecore_Fd_Handler *fd_handler;
1520 1532
1521 FD_ZERO(&read_set); 1533 FD_ZERO(&read_set);
1522 FD_ZERO(&write_set); 1534 FD_ZERO(&write_set);
@@ -1532,53 +1544,61 @@ _ecore_con_url_fdset(void)
1532 for (fd = 0; fd <= fd_max; fd++) 1544 for (fd = 0; fd <= fd_max; fd++)
1533 { 1545 {
1534 int flags = 0; 1546 int flags = 0;
1535 if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; 1547 if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ;
1536 if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; 1548 if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE;
1537 if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; 1549 if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR;
1538 if (flags) 1550 if (flags)
1539 { 1551 {
1540 if (!FD_ISSET(fd, &_current_fd_set)) 1552 // FIXME: Who is owner (easy_handle) of this fd?? (Curl do not give this info.)
1541 { 1553 // This cause "Failed to delete epoll fd xx!" error messages
1542 FD_SET(fd, &_current_fd_set); 1554 Ecore_Fd_Handler *fd_handler;
1543 fd_handler = ecore_main_fd_handler_add(fd, flags, _ecore_con_url_fd_handler, NULL, NULL, NULL); 1555 fd_handler = ecore_main_fd_handler_add(fd, flags,
1544 if (fd_handler) _fd_hd_list = eina_list_append(_fd_hd_list, fd_handler); 1556 _ecore_con_url_fd_handler,
1545 ecore_timer_freeze(_curl_timeout); 1557 NULL, NULL, NULL);
1546 } 1558 if (fd_handler)
1559 _fd_hd_list = eina_list_append(_fd_hd_list, fd_handler);
1547 } 1560 }
1548 } 1561 }
1549} 1562}
1550 1563
1551static Eina_Bool 1564static Eina_Bool
1552_ecore_con_url_idler_handler(void *data __UNUSED__) 1565_ecore_con_url_timer(void *data __UNUSED__)
1553{ 1566{
1567 Ecore_Fd_Handler *fdh;
1554 int still_running; 1568 int still_running;
1555 CURLMcode ret; 1569 CURLMcode ret;
1556 1570
1571 EINA_LIST_FREE(_fd_hd_list, fdh) ecore_main_fd_handler_del(fdh);
1572 _ecore_con_url_info_read();
1573
1557 ret = curl_multi_perform(_curlm, &still_running); 1574 ret = curl_multi_perform(_curlm, &still_running);
1558 if (ret == CURLM_CALL_MULTI_PERFORM) 1575 if (ret == CURLM_CALL_MULTI_PERFORM)
1559 { 1576 {
1560 DBG("Call multiperform again"); 1577 DBG("curl_multi_perform() again immediately");
1561 return ECORE_CALLBACK_RENEW; 1578 return ECORE_CALLBACK_RENEW;
1562 } 1579 }
1563 else if (ret != CURLM_OK) 1580 else if (ret != CURLM_OK)
1564 { 1581 {
1565 ERR("curl_multi_perform() failed: %s", curl_multi_strerror(ret)); 1582 ERR("curl_multi_perform() failed: %s", curl_multi_strerror(ret));
1566 _ecore_con_url_curl_clear(); 1583 _ecore_con_url_curl_clear();
1567 ecore_timer_freeze(_curl_timeout); 1584 ecore_timer_freeze(_curl_timer);
1568 return ECORE_CALLBACK_RENEW;
1569 } 1585 }
1570 1586
1571 _ecore_con_url_info_read();
1572 if (still_running) 1587 if (still_running)
1573 { 1588 {
1574 DBG("multiperform is still_running"); 1589 long ms;
1575 _ecore_con_url_fdset(); 1590 _ecore_con_url_fdset();
1591 curl_multi_timeout(_curlm, &ms);
1592 DBG("multiperform is still running: %d, timeout: %ld", still_running, ms);
1593 if (ms >= CURL_MIN_TIMEOUT || ms <= 0) ms = CURL_MIN_TIMEOUT;
1594 ecore_timer_interval_set(_curl_timer, (double)ms / 1000);
1576 } 1595 }
1577 else 1596 else
1578 { 1597 {
1579 DBG("multiperform ended"); 1598 DBG("multiperform ended");
1599 _ecore_con_url_info_read();
1580 _ecore_con_url_curl_clear(); 1600 _ecore_con_url_curl_clear();
1581 ecore_timer_freeze(_curl_timeout); 1601 ecore_timer_freeze(_curl_timer);
1582 } 1602 }
1583 1603
1584 return ECORE_CALLBACK_RENEW; 1604 return ECORE_CALLBACK_RENEW;
@@ -1596,17 +1616,20 @@ _ecore_con_url_perform(Ecore_Con_Url *url_con)
1596 return EINA_FALSE; 1616 return EINA_FALSE;
1597 } 1617 }
1598 1618
1619 url_con->multi = EINA_TRUE;
1599 _url_con_list = eina_list_append(_url_con_list, url_con); 1620 _url_con_list = eina_list_append(_url_con_list, url_con);
1600 ecore_timer_thaw(_curl_timeout); 1621 ecore_timer_thaw(_curl_timer);
1601 1622
1602 return EINA_TRUE; 1623 return EINA_TRUE;
1603} 1624}
1604 1625
1605static void 1626static void
1606_ecore_con_event_url_free(void *data __UNUSED__, 1627_ecore_con_event_url_free(Ecore_Con_Url *url_con, void *ev)
1607 void *ev)
1608{ 1628{
1609 free(ev); 1629 free(ev);
1630 url_con->event_count--;
1631 if (url_con->dead && (!url_con->event_count))
1632 ecore_con_url_free(url_con);
1610} 1633}
1611 1634
1612#endif 1635#endif