diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_con/ecore_con_url.c | 734 |
1 files changed, 387 insertions, 347 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 cfcf095..709b554 100644 --- a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c +++ b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c | |||
@@ -35,8 +35,6 @@ int ECORE_CON_EVENT_URL_COMPLETE = 0; | |||
35 | int ECORE_CON_EVENT_URL_PROGRESS = 0; | 35 | int ECORE_CON_EVENT_URL_PROGRESS = 0; |
36 | 36 | ||
37 | #ifdef HAVE_CURL | 37 | #ifdef HAVE_CURL |
38 | static Eina_Bool _ecore_con_url_fd_handler(void *data, | ||
39 | Ecore_Fd_Handler *fd_handler); | ||
40 | static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con); | 38 | static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con); |
41 | static size_t _ecore_con_url_header_cb(void *ptr, | 39 | static size_t _ecore_con_url_header_cb(void *ptr, |
42 | size_t size, | 40 | size_t size, |
@@ -57,50 +55,18 @@ static size_t _ecore_con_url_read_cb(void *ptr, | |||
57 | void *stream); | 55 | void *stream); |
58 | static void _ecore_con_event_url_free(void *data __UNUSED__, | 56 | static void _ecore_con_event_url_free(void *data __UNUSED__, |
59 | void *ev); | 57 | void *ev); |
60 | static int _ecore_con_url_process_completed_jobs( | ||
61 | Ecore_Con_Url *url_con_to_match); | ||
62 | static Eina_Bool _ecore_con_url_idler_handler(void *data); | 58 | static Eina_Bool _ecore_con_url_idler_handler(void *data); |
59 | static Eina_Bool _ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__); | ||
60 | static Eina_Bool _ecore_con_url_timeout_cb(void *data); | ||
63 | 61 | ||
64 | static Ecore_Idler *_fd_idler_handler = NULL; | ||
65 | static Eina_List *_url_con_list = NULL; | 62 | static Eina_List *_url_con_list = NULL; |
63 | static Eina_List *_fd_hd_list = NULL; | ||
66 | static CURLM *_curlm = NULL; | 64 | static CURLM *_curlm = NULL; |
67 | static fd_set _current_fd_set; | 65 | static fd_set _current_fd_set; |
68 | static int _init_count = 0; | 66 | static int _init_count = 0; |
69 | static Ecore_Timer *_curl_timeout = NULL; | 67 | static Ecore_Timer *_curl_timeout = NULL; |
70 | static Eina_Bool pipelining = EINA_FALSE; | 68 | static Eina_Bool pipelining = EINA_FALSE; |
71 | 69 | ||
72 | typedef struct _Ecore_Con_Url_Event Ecore_Con_Url_Event; | ||
73 | struct _Ecore_Con_Url_Event | ||
74 | { | ||
75 | int type; | ||
76 | void *ev; | ||
77 | }; | ||
78 | |||
79 | static Eina_Bool | ||
80 | _url_complete_idler_cb(void *data) | ||
81 | { | ||
82 | Ecore_Con_Url_Event *lev; | ||
83 | |||
84 | lev = data; | ||
85 | ecore_event_add(lev->type, lev->ev, _ecore_con_event_url_free, NULL); | ||
86 | free(lev); | ||
87 | |||
88 | return ECORE_CALLBACK_CANCEL; | ||
89 | } | ||
90 | |||
91 | static void | ||
92 | _url_complete_push_event(int type, | ||
93 | void *ev) | ||
94 | { | ||
95 | Ecore_Con_Url_Event *lev; | ||
96 | |||
97 | lev = malloc(sizeof(Ecore_Con_Url_Event)); | ||
98 | lev->type = type; | ||
99 | lev->ev = ev; | ||
100 | |||
101 | ecore_idler_add(_url_complete_idler_cb, lev); | ||
102 | } | ||
103 | |||
104 | #endif | 70 | #endif |
105 | 71 | ||
106 | /** | 72 | /** |
@@ -113,51 +79,30 @@ EAPI int | |||
113 | ecore_con_url_init(void) | 79 | ecore_con_url_init(void) |
114 | { | 80 | { |
115 | #ifdef HAVE_CURL | 81 | #ifdef HAVE_CURL |
116 | _init_count++; | 82 | if (++_init_count > 1) return _init_count; |
117 | |||
118 | if (_init_count > 1) | ||
119 | return _init_count; | ||
120 | 83 | ||
121 | if (!ECORE_CON_EVENT_URL_DATA) | 84 | if (!ECORE_CON_EVENT_URL_DATA) ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); |
122 | { | 85 | if (!ECORE_CON_EVENT_URL_COMPLETE) ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); |
123 | ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); | 86 | if (!ECORE_CON_EVENT_URL_PROGRESS) ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new(); |
124 | ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); | ||
125 | ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new(); | ||
126 | } | ||
127 | 87 | ||
128 | if (!_curlm) | 88 | if (!_curlm) |
129 | { | 89 | { |
130 | long ms; | 90 | long ms; |
131 | 91 | ||
132 | FD_ZERO(&_current_fd_set); | 92 | // curl_global_init() is not thread safe! |
133 | if (curl_global_init(CURL_GLOBAL_ALL)) | 93 | if (curl_global_init(CURL_GLOBAL_ALL)) return --_init_count; |
134 | { | ||
135 | while (_url_con_list) | ||
136 | ecore_con_url_free(eina_list_data_get(_url_con_list)); | ||
137 | return 0; | ||
138 | } | ||
139 | 94 | ||
140 | _curlm = curl_multi_init(); | 95 | _curlm = curl_multi_init(); |
141 | if (!_curlm) | 96 | if (!_curlm) return --_init_count; |
142 | { | ||
143 | while (_url_con_list) | ||
144 | ecore_con_url_free(eina_list_data_get(_url_con_list)); | ||
145 | |||
146 | _init_count--; | ||
147 | return 0; | ||
148 | } | ||
149 | 97 | ||
150 | curl_multi_timeout(_curlm, &ms); | 98 | curl_multi_timeout(_curlm, &ms); |
151 | if (ms <= 0) | 99 | if (ms <= 0) ms = 100; |
152 | ms = 1000; | ||
153 | 100 | ||
154 | _curl_timeout = | 101 | _curl_timeout = ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler, (void *)0xACE); |
155 | ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler, | ||
156 | (void *)0xACE); | ||
157 | ecore_timer_freeze(_curl_timeout); | 102 | ecore_timer_freeze(_curl_timeout); |
158 | } | 103 | } |
159 | 104 | ||
160 | return 1; | 105 | return _init_count; |
161 | #else | 106 | #else |
162 | return 0; | 107 | return 0; |
163 | #endif | 108 | #endif |
@@ -167,34 +112,31 @@ EAPI int | |||
167 | ecore_con_url_shutdown(void) | 112 | ecore_con_url_shutdown(void) |
168 | { | 113 | { |
169 | #ifdef HAVE_CURL | 114 | #ifdef HAVE_CURL |
170 | if (!_init_count) | 115 | if (_init_count == 0) return 0; |
171 | return 0; | ||
172 | |||
173 | _init_count--; | ||
174 | 116 | ||
175 | if (_init_count != 0) | 117 | if (--_init_count == 0) |
176 | return _init_count; | 118 | { |
177 | 119 | Ecore_Con_Url *con_url; | |
178 | if (_fd_idler_handler) | 120 | Ecore_Fd_Handler *fd_handler; |
179 | ecore_idler_del(_fd_idler_handler); | ||
180 | |||
181 | _fd_idler_handler = NULL; | ||
182 | |||
183 | if (_curl_timeout) | ||
184 | ecore_timer_del(_curl_timeout); | ||
185 | |||
186 | _curl_timeout = NULL; | ||
187 | 121 | ||
188 | while (_url_con_list) | 122 | if (_curl_timeout) |
189 | ecore_con_url_free(eina_list_data_get(_url_con_list)); | 123 | { |
124 | ecore_timer_del(_curl_timeout); | ||
125 | _curl_timeout = NULL; | ||
126 | } | ||
190 | 127 | ||
191 | if (_curlm) | 128 | FD_ZERO(&_current_fd_set); |
192 | { | 129 | EINA_LIST_FREE(_url_con_list, con_url) ecore_con_url_free(con_url); |
193 | curl_multi_cleanup(_curlm); | 130 | EINA_LIST_FREE(_fd_hd_list, fd_handler) ecore_main_fd_handler_del(fd_handler); |
194 | _curlm = NULL; | ||
195 | } | ||
196 | 131 | ||
197 | curl_global_cleanup(); | 132 | if (_curlm) |
133 | { | ||
134 | curl_multi_cleanup(_curlm); | ||
135 | _curlm = NULL; | ||
136 | } | ||
137 | curl_global_cleanup(); | ||
138 | } | ||
139 | return _init_count; | ||
198 | #endif | 140 | #endif |
199 | return 1; | 141 | return 1; |
200 | } | 142 | } |
@@ -237,7 +179,6 @@ ecore_con_url_new(const char *url) | |||
237 | if (!url_con) | 179 | if (!url_con) |
238 | return NULL; | 180 | return NULL; |
239 | 181 | ||
240 | url_con->fd = -1; | ||
241 | url_con->write_fd = -1; | 182 | url_con->write_fd = -1; |
242 | 183 | ||
243 | url_con->curl_easy = curl_easy_init(); | 184 | url_con->curl_easy = curl_easy_init(); |
@@ -255,6 +196,24 @@ ecore_con_url_new(const char *url) | |||
255 | return NULL; | 196 | return NULL; |
256 | } | 197 | } |
257 | 198 | ||
199 | url_con->proxy_type = -1; | ||
200 | if (_ecore_con_proxy_global) | ||
201 | { | ||
202 | if (_ecore_con_proxy_global->ip) | ||
203 | { | ||
204 | char host[128]; | ||
205 | if (_ecore_con_proxy_global->port > 0 && | ||
206 | _ecore_con_proxy_global->port <= 65535) | ||
207 | snprintf(host, sizeof(host), "socks4://%s:%d", | ||
208 | _ecore_con_proxy_global->ip, | ||
209 | _ecore_con_proxy_global->port); | ||
210 | else | ||
211 | snprintf(host, sizeof(host), "socks4://%s", | ||
212 | _ecore_con_proxy_global->ip); | ||
213 | ecore_con_url_proxy_set(url_con, host); | ||
214 | } | ||
215 | } | ||
216 | |||
258 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate"); | 217 | ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate"); |
259 | if (ret != CURLE_OK) | 218 | if (ret != CURLE_OK) |
260 | { | 219 | { |
@@ -344,43 +303,30 @@ ecore_con_url_free(Ecore_Con_Url *url_con) | |||
344 | } | 303 | } |
345 | 304 | ||
346 | ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE); | 305 | ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE); |
347 | if(url_con->fd != -1) | ||
348 | { | ||
349 | FD_CLR(url_con->fd, &_current_fd_set); | ||
350 | if (url_con->fd_handler) | ||
351 | ecore_main_fd_handler_del(url_con->fd_handler); | ||
352 | |||
353 | url_con->fd = -1; | ||
354 | url_con->fd_handler = NULL; | ||
355 | } | ||
356 | 306 | ||
357 | if (url_con->curl_easy) | 307 | if (url_con->curl_easy) |
358 | { | 308 | { |
359 | // FIXME: For an unknown reason, progress continue to arrive after destruction | ||
360 | // this prevent any further call to the callback. | ||
361 | curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL); | 309 | curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL); |
362 | curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE); | 310 | curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE); |
363 | 311 | ||
364 | if (url_con->active) | 312 | if (eina_list_data_find(_url_con_list, url_con)) |
365 | { | 313 | { |
366 | url_con->active = EINA_FALSE; | ||
367 | |||
368 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); | 314 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); |
369 | if (ret != CURLM_OK) | 315 | if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret)); |
370 | ERR("curl_multi_remove_handle failed: %s", | 316 | _url_con_list = eina_list_remove(_url_con_list, url_con); |
371 | curl_multi_strerror(ret)); | ||
372 | } | 317 | } |
373 | 318 | ||
374 | curl_easy_cleanup(url_con->curl_easy); | 319 | curl_easy_cleanup(url_con->curl_easy); |
375 | } | 320 | } |
321 | if (url_con->timer) ecore_timer_del(url_con->timer); | ||
376 | 322 | ||
377 | _url_con_list = eina_list_remove(_url_con_list, url_con); | ||
378 | curl_slist_free_all(url_con->headers); | 323 | curl_slist_free_all(url_con->headers); |
379 | EINA_LIST_FREE(url_con->additional_headers, s) | 324 | EINA_LIST_FREE(url_con->additional_headers, s) |
380 | free(s); | 325 | free(s); |
381 | EINA_LIST_FREE(url_con->response_headers, s) | 326 | EINA_LIST_FREE(url_con->response_headers, s) |
382 | free(s); | 327 | free(s); |
383 | eina_stringshare_del(url_con->url); | 328 | eina_stringshare_del(url_con->url); |
329 | if (url_con->post_data) free(url_con->post_data); | ||
384 | free(url_con); | 330 | free(url_con); |
385 | #else | 331 | #else |
386 | return; | 332 | return; |
@@ -415,8 +361,7 @@ ecore_con_url_url_set(Ecore_Con_Url *url_con, | |||
415 | return EINA_FALSE; | 361 | return EINA_FALSE; |
416 | } | 362 | } |
417 | 363 | ||
418 | if (url_con->active) | 364 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; |
419 | return EINA_FALSE; | ||
420 | 365 | ||
421 | eina_stringshare_replace(&url_con->url, url); | 366 | eina_stringshare_replace(&url_con->url, url); |
422 | 367 | ||
@@ -660,7 +605,7 @@ _ecore_con_url_send(Ecore_Con_Url *url_con, | |||
660 | #ifdef HAVE_CURL | 605 | #ifdef HAVE_CURL |
661 | Eina_List *l; | 606 | Eina_List *l; |
662 | const char *s; | 607 | const char *s; |
663 | char tmp[256]; | 608 | char tmp[512]; |
664 | 609 | ||
665 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | 610 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) |
666 | { | 611 | { |
@@ -668,8 +613,7 @@ _ecore_con_url_send(Ecore_Con_Url *url_con, | |||
668 | return EINA_FALSE; | 613 | return EINA_FALSE; |
669 | } | 614 | } |
670 | 615 | ||
671 | if (url_con->active) | 616 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; |
672 | return EINA_FALSE; | ||
673 | 617 | ||
674 | if (!url_con->url) | 618 | if (!url_con->url) |
675 | return EINA_FALSE; | 619 | return EINA_FALSE; |
@@ -684,16 +628,24 @@ _ecore_con_url_send(Ecore_Con_Url *url_con, | |||
684 | 628 | ||
685 | if ((mode == MODE_POST) || (mode == MODE_AUTO)) | 629 | if ((mode == MODE_POST) || (mode == MODE_AUTO)) |
686 | { | 630 | { |
687 | if (data) | 631 | if (url_con->post_data) free(url_con->post_data); |
632 | url_con->post_data = NULL; | ||
633 | if ((data) && (length > 0)) | ||
688 | { | 634 | { |
689 | if ((content_type) && (strlen(content_type) < 200)) | 635 | url_con->post_data = malloc(length); |
636 | if (url_con->post_data) | ||
690 | { | 637 | { |
691 | snprintf(tmp, sizeof(tmp), "Content-Type: %s", content_type); | 638 | memcpy(url_con->post_data, data, length); |
692 | url_con->headers = curl_slist_append(url_con->headers, tmp); | 639 | if ((content_type) && (strlen(content_type) < 450)) |
640 | { | ||
641 | snprintf(tmp, sizeof(tmp), "Content-Type: %s", content_type); | ||
642 | url_con->headers = curl_slist_append(url_con->headers, tmp); | ||
643 | } | ||
644 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, url_con->post_data); | ||
645 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length); | ||
693 | } | 646 | } |
694 | 647 | else | |
695 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, data); | 648 | return EINA_FALSE; |
696 | curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length); | ||
697 | } | 649 | } |
698 | else curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, 0); | 650 | else curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, 0); |
699 | if (mode == MODE_POST) | 651 | if (mode == MODE_POST) |
@@ -787,8 +739,7 @@ ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, | |||
787 | return EINA_FALSE; | 739 | return EINA_FALSE; |
788 | } | 740 | } |
789 | 741 | ||
790 | if (url_con->active) | 742 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; |
791 | return EINA_FALSE; | ||
792 | 743 | ||
793 | if (!url_con->url) | 744 | if (!url_con->url) |
794 | return EINA_FALSE; | 745 | return EINA_FALSE; |
@@ -1021,8 +972,7 @@ ecore_con_url_verbose_set(Ecore_Con_Url *url_con, | |||
1021 | return; | 972 | return; |
1022 | } | 973 | } |
1023 | 974 | ||
1024 | if (url_con->active) | 975 | if (eina_list_data_find(_url_con_list, url_con)) return; |
1025 | return; | ||
1026 | 976 | ||
1027 | if (!url_con->url) | 977 | if (!url_con->url) |
1028 | return; | 978 | return; |
@@ -1047,8 +997,7 @@ ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, | |||
1047 | return; | 997 | return; |
1048 | } | 998 | } |
1049 | 999 | ||
1050 | if (url_con->active) | 1000 | if (eina_list_data_find(_url_con_list, url_con)) return; |
1051 | return; | ||
1052 | 1001 | ||
1053 | if (!url_con->url) | 1002 | if (!url_con->url) |
1054 | return; | 1003 | return; |
@@ -1085,8 +1034,7 @@ ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con, | |||
1085 | return; | 1034 | return; |
1086 | } | 1035 | } |
1087 | 1036 | ||
1088 | if (url_con->active) | 1037 | if (eina_list_data_find(_url_con_list, url_con)) return; |
1089 | return; | ||
1090 | 1038 | ||
1091 | if (!url_con->url) | 1039 | if (!url_con->url) |
1092 | return; | 1040 | return; |
@@ -1129,7 +1077,7 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path) | |||
1129 | return -1; | 1077 | return -1; |
1130 | } | 1078 | } |
1131 | 1079 | ||
1132 | if (url_con->active) return -1; | 1080 | if (eina_list_data_find(_url_con_list, url_con)) return -1; |
1133 | if (!url_con->url) return -1; | 1081 | if (!url_con->url) return -1; |
1134 | if (ca_path == NULL) | 1082 | if (ca_path == NULL) |
1135 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0); | 1083 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0); |
@@ -1148,58 +1096,180 @@ ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path) | |||
1148 | return res; | 1096 | return res; |
1149 | } | 1097 | } |
1150 | 1098 | ||
1151 | 1099 | EAPI Eina_Bool | |
1152 | /** | 1100 | ecore_con_url_proxy_set(Ecore_Con_Url *url_con, const char *proxy) |
1153 | * @} | ||
1154 | */ | ||
1155 | |||
1156 | #ifdef HAVE_CURL | ||
1157 | static int | ||
1158 | _ecore_con_url_suspend_fd_handler(void) | ||
1159 | { | 1101 | { |
1160 | Eina_List *l; | 1102 | #ifdef HAVE_CURL |
1161 | Ecore_Con_Url *url_con; | 1103 | int res = -1; |
1162 | int deleted = 0; | 1104 | curl_version_info_data *vers = NULL; |
1163 | 1105 | ||
1164 | if (!_url_con_list) | 1106 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) |
1165 | return 0; | 1107 | { |
1108 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_set"); | ||
1109 | return EINA_FALSE; | ||
1110 | } | ||
1166 | 1111 | ||
1167 | EINA_LIST_FOREACH(_url_con_list, l, url_con) | 1112 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; |
1113 | if (!url_con->url) return EINA_FALSE; | ||
1114 | |||
1115 | if (!proxy) res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, ""); | ||
1116 | else | ||
1168 | { | 1117 | { |
1169 | if (url_con->active && url_con->fd_handler) | 1118 | // before curl version 7.21.7, socks protocol:// prefix is not supported |
1119 | // (e.g. socks4://, socks4a://, socks5:// or socks5h://, etc.) | ||
1120 | vers = curl_version_info(CURLVERSION_NOW); | ||
1121 | if (vers->version_num < 0x71507) | ||
1170 | { | 1122 | { |
1171 | ecore_main_fd_handler_del(url_con->fd_handler); | 1123 | url_con->proxy_type = CURLPROXY_HTTP; |
1172 | url_con->fd_handler = NULL; | 1124 | if (strstr(proxy, "socks4")) url_con->proxy_type = CURLPROXY_SOCKS4; |
1173 | deleted++; | 1125 | else if (strstr(proxy, "socks4a")) url_con->proxy_type = CURLPROXY_SOCKS4A; |
1126 | else if (strstr(proxy, "socks5")) url_con->proxy_type = CURLPROXY_SOCKS5; | ||
1127 | else if (strstr(proxy, "socks5h")) url_con->proxy_type = CURLPROXY_SOCKS5_HOSTNAME; | ||
1128 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXYTYPE, url_con->proxy_type); | ||
1129 | if (res != CURLE_OK) | ||
1130 | { | ||
1131 | ERR("curl proxy type setting failed: %s", curl_easy_strerror(res)); | ||
1132 | url_con->proxy_type = -1; | ||
1133 | return EINA_FALSE; | ||
1134 | } | ||
1174 | } | 1135 | } |
1136 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PROXY, proxy); | ||
1137 | } | ||
1138 | if (res != CURLE_OK) | ||
1139 | { | ||
1140 | ERR("curl proxy setting failed: %s", curl_easy_strerror(res)); | ||
1141 | url_con->proxy_type = -1; | ||
1142 | return EINA_FALSE; | ||
1143 | } | ||
1144 | return EINA_TRUE; | ||
1145 | #else | ||
1146 | return EINA_FALSE; | ||
1147 | (void)url_con; | ||
1148 | (void)proxy; | ||
1149 | #endif | ||
1150 | } | ||
1151 | |||
1152 | EAPI void | ||
1153 | ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout) | ||
1154 | { | ||
1155 | #ifdef HAVE_CURL | ||
1156 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1157 | { | ||
1158 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_timeout_set"); | ||
1159 | return; | ||
1175 | } | 1160 | } |
1176 | 1161 | ||
1177 | return deleted; | 1162 | if (eina_list_data_find(_url_con_list, url_con)) return; |
1163 | if (!url_con->url || timeout < 0) return; | ||
1164 | 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); | ||
1166 | #else | ||
1167 | return; | ||
1168 | (void)url_con; | ||
1169 | (void)timeout; | ||
1170 | #endif | ||
1178 | } | 1171 | } |
1179 | 1172 | ||
1180 | static int | 1173 | EAPI Eina_Bool |
1181 | _ecore_con_url_restart_fd_handler(void) | 1174 | ecore_con_url_proxy_username_set(Ecore_Con_Url *url_con, const char *username) |
1182 | { | 1175 | { |
1183 | Eina_List *l; | 1176 | #ifdef HAVE_CURL |
1184 | Ecore_Con_Url *url_con; | 1177 | int res = -1; |
1185 | int activated = 0; | 1178 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) |
1179 | { | ||
1180 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_username_set"); | ||
1181 | return EINA_FALSE; | ||
1182 | } | ||
1186 | 1183 | ||
1187 | if (!_url_con_list) | 1184 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; |
1188 | return 0; | 1185 | if (!url_con->url) return EINA_FALSE; |
1186 | if (!username) return EINA_FALSE; | ||
1187 | if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) | ||
1188 | { | ||
1189 | ERR("Proxy type should be socks5 and above"); | ||
1190 | return EINA_FALSE; | ||
1191 | } | ||
1189 | 1192 | ||
1190 | EINA_LIST_FOREACH(_url_con_list, l, url_con) | 1193 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERNAME, username); |
1194 | if (res != CURLE_OK) | ||
1191 | { | 1195 | { |
1192 | if (!url_con->fd_handler && url_con->fd != -1) | 1196 | ERR("curl_easy_setopt() failed: %s", curl_easy_strerror(res)); |
1193 | { | 1197 | return EINA_FALSE; |
1194 | url_con->fd_handler = | 1198 | } |
1195 | ecore_main_fd_handler_add(url_con->fd, url_con->flags, | 1199 | return EINA_TRUE; |
1196 | _ecore_con_url_fd_handler, | 1200 | #else |
1197 | NULL, NULL, NULL); | 1201 | return EINA_FALSE; |
1198 | activated++; | 1202 | (void)url_con; |
1199 | } | 1203 | (void)username; |
1204 | #endif | ||
1205 | } | ||
1206 | |||
1207 | EAPI Eina_Bool | ||
1208 | ecore_con_url_proxy_password_set(Ecore_Con_Url *url_con, const char *password) | ||
1209 | { | ||
1210 | #ifdef HAVE_CURL | ||
1211 | int res = -1; | ||
1212 | if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL)) | ||
1213 | { | ||
1214 | ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_proxy_password_set"); | ||
1215 | return EINA_FALSE; | ||
1216 | } | ||
1217 | if (eina_list_data_find(_url_con_list, url_con)) return EINA_FALSE; | ||
1218 | if (!url_con->url) return EINA_FALSE; | ||
1219 | if (!password) return EINA_FALSE; | ||
1220 | if (url_con->proxy_type == CURLPROXY_SOCKS4 || url_con->proxy_type == CURLPROXY_SOCKS4A) | ||
1221 | { | ||
1222 | ERR("Proxy type should be socks5 and above"); | ||
1223 | return EINA_FALSE; | ||
1224 | } | ||
1225 | |||
1226 | res = curl_easy_setopt(url_con->curl_easy, CURLOPT_PASSWORD, password); | ||
1227 | if (res != CURLE_OK) | ||
1228 | { | ||
1229 | ERR("curl_easy_setopt() failed: %s", curl_easy_strerror(res)); | ||
1230 | return EINA_FALSE; | ||
1200 | } | 1231 | } |
1232 | return EINA_TRUE; | ||
1233 | #else | ||
1234 | return EINA_FALSE; | ||
1235 | (void)url_con; | ||
1236 | (void)password; | ||
1237 | #endif | ||
1238 | } | ||
1239 | |||
1240 | /** | ||
1241 | * @} | ||
1242 | */ | ||
1201 | 1243 | ||
1202 | return activated; | 1244 | #ifdef HAVE_CURL |
1245 | static Eina_Bool | ||
1246 | _ecore_con_url_timeout_cb(void *data) | ||
1247 | { | ||
1248 | Ecore_Con_Url *url_con = data; | ||
1249 | CURLMcode ret; | ||
1250 | Ecore_Con_Event_Url_Complete *e; | ||
1251 | |||
1252 | if (!url_con) return ECORE_CALLBACK_CANCEL; | ||
1253 | 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 | |||
1256 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); | ||
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); | ||
1259 | |||
1260 | curl_slist_free_all(url_con->headers); | ||
1261 | url_con->headers = NULL; | ||
1262 | |||
1263 | url_con->timer = NULL; | ||
1264 | |||
1265 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); | ||
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; | ||
1203 | } | 1273 | } |
1204 | 1274 | ||
1205 | static size_t | 1275 | static size_t |
@@ -1235,8 +1305,7 @@ _ecore_con_url_data_cb(void *buffer, | |||
1235 | e->url_con = url_con; | 1305 | e->url_con = url_con; |
1236 | e->size = real_size; | 1306 | e->size = real_size; |
1237 | memcpy(e->data, buffer, real_size); | 1307 | memcpy(e->data, buffer, real_size); |
1238 | ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, | 1308 | ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, _ecore_con_event_url_free, NULL); |
1239 | _ecore_con_event_url_free, NULL); | ||
1240 | } | 1309 | } |
1241 | } | 1310 | } |
1242 | else | 1311 | else |
@@ -1266,22 +1335,6 @@ _ecore_con_url_data_cb(void *buffer, | |||
1266 | return real_size; | 1335 | return real_size; |
1267 | } | 1336 | } |
1268 | 1337 | ||
1269 | #define ECORE_CON_URL_TRANSMISSION(Transmit, Event, Url_con, Total, Now) \ | ||
1270 | { \ | ||
1271 | Ecore_Con_Event_Url_Progress *e; \ | ||
1272 | if ((Total != 0) || (Now != 0)) \ | ||
1273 | { \ | ||
1274 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress)); \ | ||
1275 | if (e) \ | ||
1276 | { \ | ||
1277 | e->url_con = url_con; \ | ||
1278 | e->total = Total; \ | ||
1279 | e->now = Now; \ | ||
1280 | ecore_event_add(Event, e, _ecore_con_event_url_free, NULL); \ | ||
1281 | } \ | ||
1282 | } \ | ||
1283 | } | ||
1284 | |||
1285 | static size_t | 1338 | static size_t |
1286 | _ecore_con_url_header_cb(void *ptr, | 1339 | _ecore_con_url_header_cb(void *ptr, |
1287 | size_t size, | 1340 | size_t size, |
@@ -1324,8 +1377,7 @@ _ecore_con_url_progress_cb(void *clientp, | |||
1324 | e->down.now = dlnow; | 1377 | e->down.now = dlnow; |
1325 | e->up.total = ultotal; | 1378 | e->up.total = ultotal; |
1326 | e->up.now = ulnow; | 1379 | e->up.now = ulnow; |
1327 | ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, | 1380 | ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e, _ecore_con_event_url_free, NULL); |
1328 | _ecore_con_event_url_free, NULL); | ||
1329 | } | 1381 | } |
1330 | 1382 | ||
1331 | return 0; | 1383 | return 0; |
@@ -1358,208 +1410,196 @@ _ecore_con_url_read_cb(void *ptr, | |||
1358 | return retcode; | 1410 | return retcode; |
1359 | } | 1411 | } |
1360 | 1412 | ||
1361 | static Eina_Bool | 1413 | static void |
1362 | _ecore_con_url_perform(Ecore_Con_Url *url_con) | 1414 | _ecore_con_url_info_read(void) |
1363 | { | 1415 | { |
1364 | fd_set read_set, write_set, exc_set; | 1416 | CURLMsg *curlmsg; |
1365 | int fd_max, fd; | 1417 | int n_remaining; |
1366 | int flags, still_running; | ||
1367 | int completed_immediately = 0; | ||
1368 | CURLMcode ret; | ||
1369 | |||
1370 | _url_con_list = eina_list_append(_url_con_list, url_con); | ||
1371 | |||
1372 | url_con->active = EINA_TRUE; | ||
1373 | curl_multi_add_handle(_curlm, url_con->curl_easy); | ||
1374 | curl_multi_perform(_curlm, &still_running); | ||
1375 | |||
1376 | completed_immediately = _ecore_con_url_process_completed_jobs(url_con); | ||
1377 | 1418 | ||
1378 | if (!completed_immediately) | 1419 | while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining))) |
1379 | { | 1420 | { |
1380 | if (url_con->fd_handler) | 1421 | if (curlmsg->msg == CURLMSG_DONE) |
1381 | ecore_main_fd_handler_del(url_con->fd_handler); | ||
1382 | |||
1383 | url_con->fd_handler = NULL; | ||
1384 | |||
1385 | /* url_con still active -- set up an fd_handler */ | ||
1386 | FD_ZERO(&read_set); | ||
1387 | FD_ZERO(&write_set); | ||
1388 | FD_ZERO(&exc_set); | ||
1389 | |||
1390 | /* Stupid curl, why can't I get the fd to the current added job? */ | ||
1391 | ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set, | ||
1392 | &fd_max); | ||
1393 | if (ret != CURLM_OK) | ||
1394 | { | 1422 | { |
1395 | ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret)); | 1423 | Eina_List *l, *ll; |
1396 | return EINA_FALSE; | 1424 | Ecore_Con_Url *url_con; |
1397 | } | ||
1398 | 1425 | ||
1399 | for (fd = 0; fd <= fd_max; fd++) | 1426 | EINA_LIST_FOREACH_SAFE(_url_con_list, l, ll, url_con) |
1400 | { | ||
1401 | if (!FD_ISSET(fd, &_current_fd_set)) | ||
1402 | { | 1427 | { |
1403 | flags = 0; | 1428 | if (curlmsg->easy_handle == url_con->curl_easy) |
1404 | if (FD_ISSET(fd, &read_set)) | 1429 | { |
1405 | flags |= ECORE_FD_READ; | 1430 | CURLMcode ret; |
1406 | 1431 | Ecore_Con_Event_Url_Complete *e; | |
1407 | if (FD_ISSET(fd, &write_set)) | ||
1408 | flags |= ECORE_FD_WRITE; | ||
1409 | 1432 | ||
1410 | if (FD_ISSET(fd, &exc_set)) | 1433 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); |
1411 | flags |= ECORE_FD_ERROR; | 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 | } | ||
1412 | 1447 | ||
1413 | if (flags) | 1448 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); |
1414 | { | 1449 | if (ret != CURLM_OK) ERR("curl_multi_remove_handle failed: %s", curl_multi_strerror(ret)); |
1415 | long ms = 0; | 1450 | _url_con_list = eina_list_remove(_url_con_list, url_con); |
1416 | |||
1417 | ret = curl_multi_timeout(_curlm, &ms); | ||
1418 | if (ret != CURLM_OK) | ||
1419 | ERR("curl_multi_timeout failed: %s", | ||
1420 | curl_multi_strerror(ret)); | ||
1421 | |||
1422 | if (ms == 0) | ||
1423 | ms = 1000; | ||
1424 | |||
1425 | FD_SET(fd, &_current_fd_set); | ||
1426 | url_con->fd = fd; | ||
1427 | url_con->flags = flags; | ||
1428 | url_con->fd_handler = | ||
1429 | ecore_main_fd_handler_add(fd, flags, | ||
1430 | _ecore_con_url_fd_handler, | ||
1431 | NULL, NULL, NULL); | ||
1432 | break; | 1451 | break; |
1433 | } | 1452 | } |
1434 | } | 1453 | } |
1435 | } | 1454 | } |
1436 | if (!url_con->fd_handler) | ||
1437 | { | ||
1438 | /* Failed to set up an fd_handler */ | ||
1439 | ecore_timer_freeze(_curl_timeout); | ||
1440 | |||
1441 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); | ||
1442 | if (ret != CURLM_OK) | ||
1443 | ERR("curl_multi_remove_handle failed: %s", | ||
1444 | curl_multi_strerror(ret)); | ||
1445 | |||
1446 | url_con->active = EINA_FALSE; | ||
1447 | url_con->fd = -1; | ||
1448 | return EINA_FALSE; | ||
1449 | } | ||
1450 | |||
1451 | ecore_timer_thaw(_curl_timeout); | ||
1452 | } | 1455 | } |
1453 | |||
1454 | return EINA_TRUE; | ||
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | static Eina_Bool | 1458 | static void |
1458 | _ecore_con_url_idler_handler(void *data) | 1459 | _ecore_con_url_curl_clear(void) |
1459 | { | 1460 | { |
1460 | int done, still_running; | 1461 | Ecore_Con_Url *url_con; |
1461 | |||
1462 | done = (curl_multi_perform(_curlm, &still_running) != CURLM_CALL_MULTI_PERFORM); | ||
1463 | |||
1464 | _ecore_con_url_process_completed_jobs(NULL); | ||
1465 | 1462 | ||
1466 | if (done) | 1463 | FD_ZERO(&_current_fd_set); |
1464 | if (_fd_hd_list) | ||
1467 | { | 1465 | { |
1468 | _ecore_con_url_restart_fd_handler(); | 1466 | Ecore_Fd_Handler *fd_handler; |
1469 | _fd_idler_handler = NULL; | 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 | } | ||
1470 | 1476 | ||
1471 | if (!_url_con_list) | 1477 | EINA_LIST_FREE(_url_con_list, url_con) |
1472 | ecore_timer_freeze(_curl_timeout); | 1478 | { |
1479 | CURLMcode ret; | ||
1480 | Ecore_Con_Event_Url_Complete *e; | ||
1473 | 1481 | ||
1474 | return data == | 1482 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); |
1475 | (void *)0xACE ? ECORE_CALLBACK_RENEW : ECORE_CALLBACK_CANCEL; | 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)); | ||
1476 | } | 1491 | } |
1477 | |||
1478 | return ECORE_CALLBACK_RENEW; | ||
1479 | } | 1492 | } |
1480 | 1493 | ||
1481 | static Eina_Bool | 1494 | static Eina_Bool |
1482 | _ecore_con_url_fd_handler(void *data __UNUSED__, | 1495 | _ecore_con_url_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) |
1483 | Ecore_Fd_Handler *fd_handler __UNUSED__) | ||
1484 | { | 1496 | { |
1485 | _ecore_con_url_suspend_fd_handler(); | 1497 | if (_fd_hd_list) |
1486 | 1498 | { | |
1487 | if (!_fd_idler_handler) | 1499 | Ecore_Fd_Handler *fd_handler; |
1488 | _fd_idler_handler = ecore_idler_add( | 1500 | EINA_LIST_FREE(_fd_hd_list, fd_handler) |
1489 | _ecore_con_url_idler_handler, NULL); | 1501 | { |
1490 | 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); | ||
1491 | return ECORE_CALLBACK_RENEW; | 1510 | return ECORE_CALLBACK_RENEW; |
1492 | } | 1511 | } |
1493 | 1512 | ||
1494 | static int | 1513 | static void |
1495 | _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match) | 1514 | _ecore_con_url_fdset(void) |
1496 | { | 1515 | { |
1497 | Eina_List *l; | ||
1498 | Ecore_Con_Url *url_con; | ||
1499 | Ecore_Con_Event_Url_Complete *e; | ||
1500 | CURLMsg *curlmsg; | ||
1501 | CURLMcode ret; | 1516 | CURLMcode ret; |
1502 | int n_remaining; | 1517 | fd_set read_set, write_set, exc_set; |
1503 | int job_matched = 0; | 1518 | int fd, fd_max; |
1519 | Ecore_Fd_Handler *fd_handler; | ||
1504 | 1520 | ||
1505 | /* Loop jobs and check if any are done */ | 1521 | FD_ZERO(&read_set); |
1506 | while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining))) | 1522 | FD_ZERO(&write_set); |
1523 | FD_ZERO(&exc_set); | ||
1524 | |||
1525 | ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set, &fd_max); | ||
1526 | if (ret != CURLM_OK) | ||
1507 | { | 1527 | { |
1508 | if (curlmsg->msg != CURLMSG_DONE) | 1528 | ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret)); |
1509 | continue; | 1529 | return; |
1530 | } | ||
1510 | 1531 | ||
1511 | /* find the job which is done */ | 1532 | for (fd = 0; fd <= fd_max; fd++) |
1512 | EINA_LIST_FOREACH(_url_con_list, l, url_con) | 1533 | { |
1534 | int flags = 0; | ||
1535 | if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; | ||
1536 | if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; | ||
1537 | if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; | ||
1538 | if (flags) | ||
1513 | { | 1539 | { |
1514 | if (curlmsg->easy_handle == url_con->curl_easy) | 1540 | if (!FD_ISSET(fd, &_current_fd_set)) |
1515 | { | 1541 | { |
1516 | if (url_con_to_match && | 1542 | FD_SET(fd, &_current_fd_set); |
1517 | (url_con == url_con_to_match)) | 1543 | fd_handler = ecore_main_fd_handler_add(fd, flags, _ecore_con_url_fd_handler, NULL, NULL, NULL); |
1518 | job_matched = 1; | 1544 | if (fd_handler) _fd_hd_list = eina_list_append(_fd_hd_list, fd_handler); |
1519 | 1545 | ecore_timer_freeze(_curl_timeout); | |
1520 | if(url_con->fd != -1) | 1546 | } |
1521 | { | 1547 | } |
1522 | FD_CLR(url_con->fd, &_current_fd_set); | 1548 | } |
1523 | if (url_con->fd_handler) | 1549 | } |
1524 | ecore_main_fd_handler_del( | ||
1525 | url_con->fd_handler); | ||
1526 | 1550 | ||
1527 | url_con->fd = -1; | 1551 | static Eina_Bool |
1528 | url_con->fd_handler = NULL; | 1552 | _ecore_con_url_idler_handler(void *data __UNUSED__) |
1529 | } | 1553 | { |
1554 | int still_running; | ||
1555 | CURLMcode ret; | ||
1530 | 1556 | ||
1531 | _url_con_list = eina_list_remove(_url_con_list, url_con); | 1557 | ret = curl_multi_perform(_curlm, &still_running); |
1532 | url_con->active = EINA_FALSE; | 1558 | if (ret == CURLM_CALL_MULTI_PERFORM) |
1533 | e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); | 1559 | { |
1534 | if (e) | 1560 | DBG("Call multiperform again"); |
1535 | { | 1561 | return ECORE_CALLBACK_RENEW; |
1536 | e->url_con = url_con; | 1562 | } |
1537 | e->status = 0; | 1563 | else if (ret != CURLM_OK) |
1538 | if (curlmsg->data.result == CURLE_OK) | 1564 | { |
1539 | { | 1565 | ERR("curl_multi_perform() failed: %s", curl_multi_strerror(ret)); |
1540 | long status; /* curl API uses long, not int */ | 1566 | _ecore_con_url_curl_clear(); |
1567 | ecore_timer_freeze(_curl_timeout); | ||
1568 | return ECORE_CALLBACK_RENEW; | ||
1569 | } | ||
1541 | 1570 | ||
1542 | status = 0; | 1571 | _ecore_con_url_info_read(); |
1543 | curl_easy_getinfo(curlmsg->easy_handle, | 1572 | if (still_running) |
1544 | CURLINFO_RESPONSE_CODE, | 1573 | { |
1545 | &status); | 1574 | DBG("multiperform is still_running"); |
1546 | e->status = status; | 1575 | _ecore_con_url_fdset(); |
1547 | } | 1576 | } |
1577 | else | ||
1578 | { | ||
1579 | DBG("multiperform ended"); | ||
1580 | _ecore_con_url_curl_clear(); | ||
1581 | ecore_timer_freeze(_curl_timeout); | ||
1582 | } | ||
1548 | 1583 | ||
1549 | _url_complete_push_event(ECORE_CON_EVENT_URL_COMPLETE, e); | 1584 | return ECORE_CALLBACK_RENEW; |
1550 | } | 1585 | } |
1551 | 1586 | ||
1552 | ret = curl_multi_remove_handle(_curlm, url_con->curl_easy); | 1587 | static Eina_Bool |
1553 | if (ret != CURLM_OK) | 1588 | _ecore_con_url_perform(Ecore_Con_Url *url_con) |
1554 | ERR("curl_multi_remove_handle failed: %s", | 1589 | { |
1555 | curl_multi_strerror(ret)); | 1590 | CURLMcode ret; |
1556 | 1591 | ||
1557 | break; | 1592 | ret = curl_multi_add_handle(_curlm, url_con->curl_easy); |
1558 | } | 1593 | if (ret != CURLM_OK) |
1559 | } | 1594 | { |
1595 | ERR("curl_multi_add_handle() failed: %s", curl_multi_strerror(ret)); | ||
1596 | return EINA_FALSE; | ||
1560 | } | 1597 | } |
1561 | 1598 | ||
1562 | return job_matched; | 1599 | _url_con_list = eina_list_append(_url_con_list, url_con); |
1600 | ecore_timer_thaw(_curl_timeout); | ||
1601 | |||
1602 | return EINA_TRUE; | ||
1563 | } | 1603 | } |
1564 | 1604 | ||
1565 | static void | 1605 | static void |