aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_con
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-04-22 09:19:23 +1000
committerDavid Walter Seikel2012-04-22 09:19:23 +1000
commitc963d75dfdeec11f82e79e727062fbf89afa2c04 (patch)
tree895633dbf641110be46f117c29890c49b3ffc0bd /libraries/ecore/src/lib/ecore_con
parentAdding the new extantz viewer and grid manager. (diff)
downloadSledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.zip
SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.gz
SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.bz2
SledjHamr-c963d75dfdeec11f82e79e727062fbf89afa2c04.tar.xz
Update EFL to latest beta.
Diffstat (limited to 'libraries/ecore/src/lib/ecore_con')
-rw-r--r--libraries/ecore/src/lib/ecore_con/Ecore_Con.h81
-rw-r--r--libraries/ecore/src/lib/ecore_con/Makefile.in20
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con.c23
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_private.h47
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_socks.c762
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c3
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_url.c671
7 files changed, 1052 insertions, 555 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/Ecore_Con.h b/libraries/ecore/src/lib/ecore_con/Ecore_Con.h
index c3af46a..d0ca6f6 100644
--- a/libraries/ecore/src/lib/ecore_con/Ecore_Con.h
+++ b/libraries/ecore/src/lib/ecore_con/Ecore_Con.h
@@ -723,10 +723,13 @@ EAPI Eina_Bool ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_
723 */ 723 */
724 724
725EAPI Ecore_Con_Socks *ecore_con_socks4_remote_add(const char *ip, int port, const char *username); 725EAPI Ecore_Con_Socks *ecore_con_socks4_remote_add(const char *ip, int port, const char *username);
726EAPI void ecore_con_socks4_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable);
727EAPI Eina_Bool ecore_con_socks4_lookup_get(Ecore_Con_Socks *ecs);
728EAPI Eina_Bool ecore_con_socks4_remote_exists(const char *ip, int port, const char *username); 726EAPI Eina_Bool ecore_con_socks4_remote_exists(const char *ip, int port, const char *username);
729EAPI void ecore_con_socks4_remote_del(const char *ip, int port, const char *username); 727EAPI void ecore_con_socks4_remote_del(const char *ip, int port, const char *username);
728EAPI Ecore_Con_Socks *ecore_con_socks5_remote_add(const char *ip, int port, const char *username, const char *password);
729EAPI Eina_Bool ecore_con_socks5_remote_exists(const char *ip, int port, const char *username, const char *password);
730EAPI void ecore_con_socks5_remote_del(const char *ip, int port, const char *username, const char *password);
731EAPI void ecore_con_socks_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable);
732EAPI Eina_Bool ecore_con_socks_lookup_get(Ecore_Con_Socks *ecs);
730EAPI void ecore_con_socks_bind_set(Ecore_Con_Socks *ecs, Eina_Bool is_bind); 733EAPI void ecore_con_socks_bind_set(Ecore_Con_Socks *ecs, Eina_Bool is_bind);
731EAPI Eina_Bool ecore_con_socks_bind_get(Ecore_Con_Socks *ecs); 734EAPI Eina_Bool ecore_con_socks_bind_get(Ecore_Con_Socks *ecs);
732EAPI unsigned int ecore_con_socks_version_get(Ecore_Con_Socks *ecs); 735EAPI unsigned int ecore_con_socks_version_get(Ecore_Con_Socks *ecs);
@@ -744,8 +747,8 @@ EAPI void ecore_con_socks_apply_always(Ecore_Con_Socks *ecs);
744 * 747 *
745 * Setting up a server is very simple: you just need to start it with 748 * Setting up a server is very simple: you just need to start it with
746 * ecore_con_server_add() and setup some callbacks to the events 749 * ecore_con_server_add() and setup some callbacks to the events
747 * #ECORE_CON_EVENT_CLIENT_ADD, #ECORE_CON_EVENT_CLIENT_DEL and 750 * @ref ECORE_CON_EVENT_CLIENT_ADD, @ref ECORE_CON_EVENT_CLIENT_DEL and
748 * #ECORE_CON_EVENT_CLIENT_DATA, that will be called when a client is 751 * @ref ECORE_CON_EVENT_CLIENT_DATA, that will be called when a client is
749 * communicating with the server: 752 * communicating with the server:
750 * 753 *
751 * @code 754 * @code
@@ -867,8 +870,8 @@ EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type,
867 * 870 *
868 * However, even if this call returns a valid @ref Ecore_Con_Server, the 871 * However, even if this call returns a valid @ref Ecore_Con_Server, the
869 * connection will only be successfully completed if an event of type 872 * connection will only be successfully completed if an event of type
870 * #ECORE_CON_EVENT_SERVER_ADD is received. If it fails to complete, an 873 * @ref ECORE_CON_EVENT_SERVER_ADD is received. If it fails to complete, an
871 * #ECORE_CON_EVENT_SERVER_DEL will be received. 874 * @ref ECORE_CON_EVENT_SERVER_DEL will be received.
872 * 875 *
873 * The @p data parameter can be fetched later using ecore_con_server_data_get() 876 * The @p data parameter can be fetched later using ecore_con_server_data_get()
874 * or changed with ecore_con_server_data_set(). 877 * or changed with ecore_con_server_data_set().
@@ -1335,6 +1338,35 @@ typedef enum _Ecore_Con_Url_Time
1335} Ecore_Con_Url_Time; 1338} Ecore_Con_Url_Time;
1336 1339
1337/** 1340/**
1341 * @typedef Ecore_Con_Url_Http_Version
1342 * @enum _Ecore_Con_Url_Http_Version
1343 * The http version to use
1344 * @since 1.2
1345 */
1346typedef enum _Ecore_Con_Url_Http_Version
1347{
1348 /**
1349 * HTTP version 1.0
1350 * @since 1.2
1351 */
1352 ECORE_CON_URL_HTTP_VERSION_1_0,
1353 /**
1354 * HTTP version 1.1 (default)
1355 * @since 1.2
1356 */
1357 ECORE_CON_URL_HTTP_VERSION_1_1
1358} Ecore_Con_Url_Http_Version;
1359
1360/**
1361 * Change the HTTP version used for the request
1362 * @param version The version to be used
1363 * @return EINA_TRUE on success, EINA_FALSE on failure to change version
1364 * @since 1.2
1365 * @see ecore_con_url_pipeline_get()
1366 */
1367EAPI Eina_Bool ecore_con_url_http_version_set(Ecore_Con_Url *url_con, Ecore_Con_Url_Http_Version version);
1368
1369/**
1338 * Initialises the Ecore_Con_Url library. 1370 * Initialises the Ecore_Con_Url library.
1339 * @return Number of times the library has been initialised without being 1371 * @return Number of times the library has been initialised without being
1340 * shut down. 1372 * shut down.
@@ -1554,33 +1586,6 @@ EAPI Eina_Bool ecore_con_url_httpauth_set(Ecore_Con_Url *url_con,
1554 const char *password, 1586 const char *password,
1555 Eina_Bool safe); 1587 Eina_Bool safe);
1556/** 1588/**
1557 * Sends a request.
1558 *
1559 * @param url_con Connection object to perform a request on, previously created
1560 * with ecore_con_url_new() or ecore_con_url_custom_new().
1561 * @param data Payload (data sent on the request)
1562 * @param length Payload length. If @c -1, rely on automatic length
1563 * calculation via @c strlen() on @p data.
1564 * @param content_type Content type of the payload (e.g. text/xml)
1565 *
1566 * @return #EINA_TRUE on success, #EINA_FALSE on error.
1567 *
1568 * @see ecore_con_url_custom_new()
1569 * @see ecore_con_url_additional_headers_clear()
1570 * @see ecore_con_url_additional_header_add()
1571 * @see ecore_con_url_data_set()
1572 * @see ecore_con_url_data_get()
1573 * @see ecore_con_url_response_headers_get()
1574 * @see ecore_con_url_time()
1575 * @see ecore_con_url_get()
1576 * @see ecore_con_url_post()
1577 *
1578 * @deprecated Use ecore_con_url_post() instead of this.
1579 */
1580EINA_DEPRECATED EAPI Eina_Bool ecore_con_url_send(Ecore_Con_Url *url_con,
1581 const void *data, long length,
1582 const char *content_type);
1583/**
1584 * Sends a get request. 1589 * Sends a get request.
1585 * 1590 *
1586 * @param url_con Connection object to perform a request on, previously created 1591 * @param url_con Connection object to perform a request on, previously created
@@ -1913,6 +1918,16 @@ EAPI Eina_Bool ecore_con_url_proxy_password_set(Ecore_Con_Url *url_con, const ch
1913EAPI void ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout); 1918EAPI void ecore_con_url_timeout_set(Ecore_Con_Url *url_con, double timeout);
1914 1919
1915/** 1920/**
1921 * Get the returned HTTP STATUS code
1922 *
1923 * This is used to, at any time, try to return the status code for a transmission.
1924 * @param url_con Connection object
1925 * @return A valid HTTP STATUS code, or 0 on failure
1926 *
1927 * @since 1.2
1928 */
1929EAPI int ecore_con_url_status_code_get(Ecore_Con_Url *url_con);
1930/**
1916 * @} 1931 * @}
1917 */ 1932 */
1918 1933
diff --git a/libraries/ecore/src/lib/ecore_con/Makefile.in b/libraries/ecore/src/lib/ecore_con/Makefile.in
index 58811da..c35b08e 100644
--- a/libraries/ecore/src/lib/ecore_con/Makefile.in
+++ b/libraries/ecore/src/lib/ecore_con/Makefile.in
@@ -54,16 +54,15 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_attribute.m4 \
54 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \ 54 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \
55 $(top_srcdir)/m4/efl_threads.m4 $(top_srcdir)/m4/gettext.m4 \ 55 $(top_srcdir)/m4/efl_threads.m4 $(top_srcdir)/m4/gettext.m4 \
56 $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ 56 $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
57 $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lib-ld.m4 \ 57 $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
58 $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ 58 $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
59 $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ 59 $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
60 $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ 60 $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
61 $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ 61 $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
62 $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ 62 $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
63 $(top_srcdir)/configure.ac
64am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 63am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
65 $(ACLOCAL_M4) 64 $(ACLOCAL_M4)
66mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs 65mkinstalldirs = $(install_sh) -d
67CONFIG_HEADER = $(top_builddir)/config.h 66CONFIG_HEADER = $(top_builddir)/config.h
68CONFIG_CLEAN_FILES = 67CONFIG_CLEAN_FILES =
69CONFIG_CLEAN_VPATH_FILES = 68CONFIG_CLEAN_VPATH_FILES =
@@ -210,6 +209,8 @@ EVAS_LIBS = @EVAS_LIBS@
210EVIL_CFLAGS = @EVIL_CFLAGS@ 209EVIL_CFLAGS = @EVIL_CFLAGS@
211EVIL_LIBS = @EVIL_LIBS@ 210EVIL_LIBS = @EVIL_LIBS@
212EXEEXT = @EXEEXT@ 211EXEEXT = @EXEEXT@
212EXOTIC_CFLAGS = @EXOTIC_CFLAGS@
213EXOTIC_LIBS = @EXOTIC_LIBS@
213FGREP = @FGREP@ 214FGREP = @FGREP@
214GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ 215GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
215GLIB_CFLAGS = @GLIB_CFLAGS@ 216GLIB_CFLAGS = @GLIB_CFLAGS@
@@ -265,6 +266,8 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
265PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ 266PIXMAN_CFLAGS = @PIXMAN_CFLAGS@
266PIXMAN_LIBS = @PIXMAN_LIBS@ 267PIXMAN_LIBS = @PIXMAN_LIBS@
267PKG_CONFIG = @PKG_CONFIG@ 268PKG_CONFIG = @PKG_CONFIG@
269PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
270PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
268POSUB = @POSUB@ 271POSUB = @POSUB@
269RANLIB = @RANLIB@ 272RANLIB = @RANLIB@
270SCIM_CFLAGS = @SCIM_CFLAGS@ 273SCIM_CFLAGS = @SCIM_CFLAGS@
@@ -275,6 +278,7 @@ SDL_LIBS = @SDL_LIBS@
275SED = @SED@ 278SED = @SED@
276SET_MAKE = @SET_MAKE@ 279SET_MAKE = @SET_MAKE@
277SHELL = @SHELL@ 280SHELL = @SHELL@
281SHM_OPEN_LIBS = @SHM_OPEN_LIBS@
278SSL_CFLAGS = @SSL_CFLAGS@ 282SSL_CFLAGS = @SSL_CFLAGS@
279SSL_LIBS = @SSL_LIBS@ 283SSL_LIBS = @SSL_LIBS@
280STRIP = @STRIP@ 284STRIP = @STRIP@
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con.c b/libraries/ecore/src/lib/ecore_con/ecore_con.c
index de291b3..fe83478 100644
--- a/libraries/ecore/src/lib/ecore_con/ecore_con.c
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con.c
@@ -110,7 +110,10 @@ _ecore_con_client_kill(Ecore_Con_Client *cl)
110 if (cl->delete_me) 110 if (cl->delete_me)
111 DBG("Multi kill request for client %p", cl); 111 DBG("Multi kill request for client %p", cl);
112 else 112 else
113 ecore_con_event_client_del(cl); 113 {
114 ecore_con_event_client_del(cl);
115 if (cl->buf) return;
116 }
114 INF("Lost client %s", (cl->ip) ? cl->ip : ""); 117 INF("Lost client %s", (cl->ip) ? cl->ip : "");
115 if (cl->fd_handler) 118 if (cl->fd_handler)
116 ecore_main_fd_handler_del(cl->fd_handler); 119 ecore_main_fd_handler_del(cl->fd_handler);
@@ -461,7 +464,7 @@ ecore_con_server_connect(Ecore_Con_Type compl_type,
461 (!ecore_con_lookup(svr->name, (Ecore_Con_Dns_Cb)ecore_con_socks_dns_cb, svr))) 464 (!ecore_con_lookup(svr->name, (Ecore_Con_Dns_Cb)ecore_con_socks_dns_cb, svr)))
462 goto error; 465 goto error;
463 if (svr->ecs->lookup) 466 if (svr->ecs->lookup)
464 svr->ecs_state = ECORE_CON_SOCKS_STATE_RESOLVED; 467 svr->ecs_state = ECORE_CON_PROXY_STATE_RESOLVED;
465 } 468 }
466 } 469 }
467 if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL)) 470 if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL))
@@ -1031,7 +1034,7 @@ ecore_con_event_server_del(Ecore_Con_Server *svr)
1031 e->server = svr; 1034 e->server = svr;
1032 if (svr->ecs) 1035 if (svr->ecs)
1033 { 1036 {
1034 svr->ecs_state = svr->ecs->lookup ? ECORE_CON_SOCKS_STATE_RESOLVED : ECORE_CON_SOCKS_STATE_DONE; 1037 svr->ecs_state = svr->ecs->lookup ? ECORE_CON_PROXY_STATE_RESOLVED : ECORE_CON_PROXY_STATE_DONE;
1035 eina_stringshare_replace(&svr->proxyip, NULL); 1038 eina_stringshare_replace(&svr->proxyip, NULL);
1036 svr->proxyport = 0; 1039 svr->proxyport = 0;
1037 } 1040 }
@@ -1320,7 +1323,7 @@ _ecore_con_client_free(Ecore_Con_Client *cl)
1320 if (cl->event_count) return; 1323 if (cl->event_count) return;
1321 ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE); 1324 ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE);
1322 1325
1323 free(cl->buf); 1326 if (cl->buf) eina_binbuf_free(cl->buf);
1324 1327
1325 if (cl->host_server->type & ECORE_CON_SSL) 1328 if (cl->host_server->type & ECORE_CON_SSL)
1326 ecore_con_ssl_client_shutdown(cl); 1329 ecore_con_ssl_client_shutdown(cl);
@@ -1736,7 +1739,7 @@ svr_try_connect_plain(Ecore_Con_Server *svr)
1736 if (so_err) 1739 if (so_err)
1737 { 1740 {
1738 /* we lost our server! */ 1741 /* we lost our server! */
1739 ecore_con_event_server_error(svr, strerror(errno)); 1742 ecore_con_event_server_error(svr, strerror(so_err));
1740 ERR("Connection lost: %s", strerror(so_err)); 1743 ERR("Connection lost: %s", strerror(so_err));
1741 _ecore_con_server_kill(svr); 1744 _ecore_con_server_kill(svr);
1742 return ECORE_CON_DISCONNECTED; 1745 return ECORE_CON_DISCONNECTED;
@@ -1971,9 +1974,9 @@ _ecore_con_cl_handler(void *data,
1971 ecore_con_event_server_add(svr); 1974 ecore_con_event_server_add(svr);
1972 return ECORE_CALLBACK_RENEW; 1975 return ECORE_CALLBACK_RENEW;
1973 } 1976 }
1974 if (svr->ecs && svr->ecs_state && (svr->ecs_state < ECORE_CON_SOCKS_STATE_READ) && (!svr->ecs_buf)) 1977 if (svr->ecs && svr->ecs_state && (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) && (!svr->ecs_buf))
1975 { 1978 {
1976 if (svr->ecs_state < ECORE_CON_SOCKS_STATE_INIT) 1979 if (svr->ecs_state < ECORE_CON_PROXY_STATE_INIT)
1977 { 1980 {
1978 INF("PROXY STATE++"); 1981 INF("PROXY STATE++");
1979 svr->ecs_state++; 1982 svr->ecs_state++;
@@ -2271,7 +2274,7 @@ _ecore_con_server_flush(Ecore_Con_Server *svr)
2271static void 2274static void
2272_ecore_con_client_flush(Ecore_Con_Client *cl) 2275_ecore_con_client_flush(Ecore_Con_Client *cl)
2273{ 2276{
2274 int num, count = 0; 2277 int num = 0, count = 0;
2275 2278
2276#ifdef _WIN32 2279#ifdef _WIN32
2277 if (ecore_con_local_win32_client_flush(cl)) 2280 if (ecore_con_local_win32_client_flush(cl))
@@ -2314,7 +2317,7 @@ _ecore_con_client_flush(Ecore_Con_Client *cl)
2314 } 2317 }
2315 2318
2316 if (count) ecore_con_event_client_write(cl, count); 2319 if (count) ecore_con_event_client_write(cl, count);
2317 cl->buf_offset += count; 2320 cl->buf_offset += count, num -= count;
2318 if (cl->buf_offset >= eina_binbuf_length_get(cl->buf)) 2321 if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
2319 { 2322 {
2320 cl->buf_offset = 0; 2323 cl->buf_offset = 0;
@@ -2332,7 +2335,7 @@ _ecore_con_client_flush(Ecore_Con_Client *cl)
2332 if (cl->fd_handler) 2335 if (cl->fd_handler)
2333 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); 2336 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
2334 } 2337 }
2335 else if ((count < num) && cl->fd_handler) 2338 else if (cl->fd_handler && (num >= 0))
2336 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); 2339 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
2337} 2340}
2338 2341
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_private.h b/libraries/ecore/src/lib/ecore_con/ecore_con_private.h
index 35f2310..91f5d39 100644
--- a/libraries/ecore/src/lib/ecore_con/ecore_con_private.h
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_private.h
@@ -56,7 +56,7 @@ extern int _ecore_con_log_dom;
56 56
57typedef struct _Ecore_Con_Lookup Ecore_Con_Lookup; 57typedef struct _Ecore_Con_Lookup Ecore_Con_Lookup;
58typedef struct _Ecore_Con_Info Ecore_Con_Info; 58typedef struct _Ecore_Con_Info Ecore_Con_Info;
59typedef struct Ecore_Con_Socks_v4 Ecore_Con_Socks_v4; 59typedef struct Ecore_Con_Socks Ecore_Con_Socks_v4;
60typedef struct Ecore_Con_Socks_v5 Ecore_Con_Socks_v5; 60typedef struct Ecore_Con_Socks_v5 Ecore_Con_Socks_v5;
61typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos); 61typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
62 62
@@ -83,13 +83,18 @@ typedef enum _Ecore_Con_Ssl_Handshake
83 ECORE_CON_SSL_STATE_INIT 83 ECORE_CON_SSL_STATE_INIT
84} Ecore_Con_Ssl_State; 84} Ecore_Con_Ssl_State;
85 85
86typedef enum Ecore_Con_Socks_State 86typedef enum Ecore_Con_Proxy_State
87{ 87{ /* named PROXY instead of SOCKS in case some handsome and enterprising
88 ECORE_CON_SOCKS_STATE_DONE = 0, 88 * developer decides to add HTTP CONNECT support
89 ECORE_CON_SOCKS_STATE_RESOLVED, 89 */
90 ECORE_CON_SOCKS_STATE_INIT, 90 ECORE_CON_PROXY_STATE_DONE = 0,
91 ECORE_CON_SOCKS_STATE_READ 91 ECORE_CON_PROXY_STATE_RESOLVED,
92} Ecore_Con_Socks_State; 92 ECORE_CON_PROXY_STATE_INIT,
93 ECORE_CON_PROXY_STATE_READ,
94 ECORE_CON_PROXY_STATE_AUTH,
95 ECORE_CON_PROXY_STATE_REQUEST,
96 ECORE_CON_PROXY_STATE_CONFIRM,
97} Ecore_Con_Proxy_State;
93 98
94struct _Ecore_Con_Client 99struct _Ecore_Con_Client
95{ 100{
@@ -140,7 +145,7 @@ struct _Ecore_Con_Server
140 pid_t ppid; 145 pid_t ppid;
141 /* socks */ 146 /* socks */
142 Ecore_Con_Socks *ecs; 147 Ecore_Con_Socks *ecs;
143 Ecore_Con_Socks_State ecs_state; 148 Ecore_Con_Proxy_State ecs_state;
144 int ecs_addrlen; 149 int ecs_addrlen;
145 unsigned char ecs_addr[16]; 150 unsigned char ecs_addr[16];
146 unsigned int ecs_buf_offset; 151 unsigned int ecs_buf_offset;
@@ -202,6 +207,7 @@ struct _Ecore_Con_Url
202 Eina_List *response_headers; 207 Eina_List *response_headers;
203 const char *url; 208 const char *url;
204 long proxy_type; 209 long proxy_type;
210 int status;
205 211
206 Ecore_Timer *timer; 212 Ecore_Timer *timer;
207 213
@@ -213,6 +219,10 @@ struct _Ecore_Con_Url
213 219
214 int received; 220 int received;
215 int write_fd; 221 int write_fd;
222
223 unsigned int event_count;
224 Eina_Bool dead : 1;
225 Eina_Bool multi : 1;
216}; 226};
217#endif 227#endif
218 228
@@ -239,24 +249,14 @@ struct _Ecore_Con_Lookup
239 v5 = (Ecore_Con_Socks_v5*)(X); \ 249 v5 = (Ecore_Con_Socks_v5*)(X); \
240 else 250 else
241 251
242struct Ecore_Con_Socks 252struct Ecore_Con_Socks /* v4 */
243{
244 unsigned char version;
245
246 const char *ip;
247 int port;
248 const char *username;
249 Eina_Bool lookup : 1;
250 Eina_Bool bind : 1;
251};
252
253struct Ecore_Con_Socks_v4
254{ 253{
255 unsigned char version; 254 unsigned char version;
256 255
257 const char *ip; 256 const char *ip;
258 int port; 257 int port;
259 const char *username; 258 const char *username;
259 unsigned int ulen;
260 Eina_Bool lookup : 1; 260 Eina_Bool lookup : 1;
261 Eina_Bool bind : 1; 261 Eina_Bool bind : 1;
262}; 262};
@@ -268,8 +268,13 @@ struct Ecore_Con_Socks_v5
268 const char *ip; 268 const char *ip;
269 int port; 269 int port;
270 const char *username; 270 const char *username;
271 unsigned int ulen;
271 Eina_Bool lookup : 1; 272 Eina_Bool lookup : 1;
272 Eina_Bool bind : 1; 273 Eina_Bool bind : 1;
274 /* v5 only */
275 unsigned char method;
276 const char *password;
277 unsigned int plen;
273}; 278};
274 279
275extern Ecore_Con_Socks *_ecore_con_proxy_once; 280extern Ecore_Con_Socks *_ecore_con_proxy_once;
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c b/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c
index aecaff0..686f73b 100644
--- a/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_socks.c
@@ -10,6 +10,10 @@
10#include <unistd.h> 10#include <unistd.h>
11#include <fcntl.h> 11#include <fcntl.h>
12 12
13#ifdef HAVE_SYS_SOCKET_H
14# include <sys/socket.h>
15#endif
16
13#ifdef HAVE_NETINET_TCP_H 17#ifdef HAVE_NETINET_TCP_H
14# include <netinet/tcp.h> 18# include <netinet/tcp.h>
15#endif 19#endif
@@ -36,10 +40,6 @@
36# include <arpa/inet.h> 40# include <arpa/inet.h>
37#endif 41#endif
38 42
39#ifdef HAVE_SYS_SOCKET_H
40# include <sys/socket.h>
41#endif
42
43#ifdef HAVE_SYS_UN_H 43#ifdef HAVE_SYS_UN_H
44# include <sys/un.h> 44# include <sys/un.h>
45#endif 45#endif
@@ -57,6 +57,27 @@
57#include "Ecore_Con.h" 57#include "Ecore_Con.h"
58#include "ecore_con_private.h" 58#include "ecore_con_private.h"
59 59
60/* http://tools.ietf.org/html/rfc1928
61 o X'00' NO AUTHENTICATION REQUIRED
62 o X'01' GSSAPI
63 o X'02' USERNAME/PASSWORD
64 o X'03' to X'7F' IANA ASSIGNED
65 o X'80' to X'FE' RESERVED FOR PRIVATE METHODS
66 o X'FF' NO ACCEPTABLE METHODS
67*/
68#define ECORE_CON_SOCKS_V5_METHOD_NONE 0
69#define ECORE_CON_SOCKS_V5_METHOD_GSSAPI 1
70#define ECORE_CON_SOCKS_V5_METHOD_USERPASS 2
71
72static int ECORE_CON_SOCKS_V5_METHODS[] =
73{
74 ECORE_CON_SOCKS_V5_METHOD_NONE,
75// ECORE_CON_SOCKS_V5_METHOD_GSSAPI, TODO
76 ECORE_CON_SOCKS_V5_METHOD_USERPASS
77};
78
79#define ECORE_CON_SOCKS_V5_TOTAL_METHODS sizeof(ECORE_CON_SOCKS_V5_METHODS)
80
60#define _ecore_con_server_kill(svr) do { \ 81#define _ecore_con_server_kill(svr) do { \
61 DBG("KILL %p", (svr)); \ 82 DBG("KILL %p", (svr)); \
62 _ecore_con_server_kill((svr)); \ 83 _ecore_con_server_kill((svr)); \
@@ -65,10 +86,10 @@
65Eina_List *ecore_con_socks_proxies = NULL; 86Eina_List *ecore_con_socks_proxies = NULL;
66 87
67static Ecore_Con_Socks * 88static Ecore_Con_Socks *
68_ecore_con_socks_find(unsigned char version, const char *ip, int port, const char *username) 89_ecore_con_socks_find(unsigned char version, const char *ip, int port, const char *username, size_t ulen, const char *password, size_t plen)
69{ 90{
70 Eina_List *l; 91 Eina_List *l;
71 Ecore_Con_Socks *ecs; 92 Ecore_Con_Socks_v5 *ecs;
72 93
73 if (!ecore_con_socks_proxies) return NULL; 94 if (!ecore_con_socks_proxies) return NULL;
74 95
@@ -77,8 +98,14 @@ _ecore_con_socks_find(unsigned char version, const char *ip, int port, const cha
77 if (ecs->version != version) continue; 98 if (ecs->version != version) continue;
78 if (strcmp(ecs->ip, ip)) continue; 99 if (strcmp(ecs->ip, ip)) continue;
79 if ((port != -1) && (port != ecs->port)) continue; 100 if ((port != -1) && (port != ecs->port)) continue;
101 if (ulen != ecs->ulen) continue;
80 if (username && strcmp(ecs->username, username)) continue; 102 if (username && strcmp(ecs->username, username)) continue;
81 return ecs; 103 if (version == 5)
104 {
105 if (plen != ecs->plen) continue;
106 if (password && strcmp(ecs->password, password)) continue;
107 }
108 return (Ecore_Con_Socks*)ecs;
82 } 109 }
83 return NULL; 110 return NULL;
84} 111}
@@ -94,146 +121,424 @@ _ecore_con_socks_free(Ecore_Con_Socks *ecs)
94 eina_stringshare_del(ecs->username); 121 eina_stringshare_del(ecs->username);
95 free(ecs); 122 free(ecs);
96} 123}
97///////////////////////////////////////////////////////////////////////////////////// 124
98void 125static Eina_Bool
99ecore_con_socks_shutdown(void) 126_ecore_con_socks_svr_init_v4(Ecore_Con_Server *svr, Ecore_Con_Socks_v4 *v4)
100{ 127{
101 Ecore_Con_Socks *ecs; 128 size_t addrlen, buflen, ulen = 1;
102 EINA_LIST_FREE(ecore_con_socks_proxies, ecs) 129 unsigned char *sbuf;
103 _ecore_con_socks_free(ecs); 130
104 _ecore_con_proxy_once = NULL; 131 addrlen = v4->lookup ? strlen(svr->name) + 1 : 0;
105 _ecore_con_proxy_global = NULL; 132 if (v4->username) ulen += v4->ulen;
133 buflen = sizeof(char) * (8 + ulen + addrlen);
134 sbuf = malloc(buflen);
135 if (!sbuf)
136 {
137 ecore_con_event_server_error(svr, "Memory allocation failure!");
138 _ecore_con_server_kill(svr);
139 return EINA_FALSE;
140 }
141 /* http://en.wikipedia.org/wiki/SOCKS */
142 sbuf[0] = 4;
143 sbuf[1] = v4->bind ? 2 : 1;
144 sbuf[2] = svr->port >> 8;
145 sbuf[3] = svr->port & 0xff;
146 if (addrlen)
147 {
148 sbuf[4] = sbuf[5] = sbuf[6] = 0;
149 sbuf[7] = 1;
150 }
151 else
152 /* SOCKSv4 only handles IPV4, so addrlen is always 4 */
153 memcpy(sbuf + 4, svr->ecs_addr, 4);
154 if (v4->username)
155 memcpy(sbuf + 8, v4->username, ulen);
156 else
157 sbuf[8] = 0;
158 if (addrlen) memcpy(sbuf + 8 + ulen, svr->name, addrlen);
159
160 svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen);
161 return EINA_TRUE;
106} 162}
107 163
108void 164static Eina_Bool
109ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num) 165_ecore_con_socks_svr_init_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5)
166{
167 size_t buflen;
168 unsigned int x;
169 unsigned char *sbuf;
170
171 if (v5->username)
172 buflen = sizeof(char) * (2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS);
173 else
174 buflen = 3;
175 sbuf = malloc(buflen);
176 if (!sbuf)
177 {
178 ecore_con_event_server_error(svr, "Memory allocation failure!");
179 _ecore_con_server_kill(svr);
180 return EINA_FALSE;
181 }
182 /* http://en.wikipedia.org/wiki/SOCKS
183 * http://tools.ietf.org/html/rfc1928
184 */
185 sbuf[0] = 5;
186 if (v5->username)
187 {
188 sbuf[1] = ECORE_CON_SOCKS_V5_TOTAL_METHODS;
189 for (x = 2; x < 2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS; x++)
190 sbuf[x] = ECORE_CON_SOCKS_V5_METHODS[x - 2];
191 }
192 else
193 {
194 sbuf[1] = 1;
195 sbuf[2] = ECORE_CON_SOCKS_V5_METHOD_NONE;
196 }
197
198 svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen);
199 return EINA_TRUE;
200}
201
202#define ECORE_CON_SOCKS_READ(EXACT) \
203 if (num < EXACT) \
204 { \
205 if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new(); \
206 if (!svr->ecs_recvbuf) goto error; \
207 eina_binbuf_append_length(svr->ecs_recvbuf, buf, num); \
208 /* the slowest connection on earth */ \
209 if (eina_binbuf_length_get(svr->ecs_recvbuf) != EXACT) return; \
210 data = eina_binbuf_string_get(svr->ecs_recvbuf); \
211 } \
212 else if (num > EXACT) goto error; \
213 else \
214 data = buf
215
216static void
217_ecore_con_socks_read_v4(Ecore_Con_Server *svr, Ecore_Con_Socks_v4 *v4 __UNUSED__, const unsigned char *buf, unsigned int num)
110{ 218{
111 const unsigned char *data; 219 const unsigned char *data;
112 ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return; 220 DBG("SOCKS: %d bytes", num);
221 ECORE_CON_SOCKS_READ(8);
113 222
114 if (svr->ecs_state != ECORE_CON_SOCKS_STATE_READ) return; 223/* http://ufasoft.com/doc/socks4_protocol.htm */
224 if (data[0]) goto error;
225 switch (data[1])
226 {
227 case 90:
228 /* success! */
229 break;
230 case 91:
231 ecore_con_event_server_error(svr, "proxy request rejected or failed");
232 goto error;
233 case 92:
234 ecore_con_event_server_error(svr, "proxying SOCKS server could not perform authentication");
235 goto error;
236 case 93:
237 ecore_con_event_server_error(svr, "proxy request authentication rejected");
238 goto error;
239 default:
240 ecore_con_event_server_error(svr, "garbage data from proxy");
241 goto error;
242 }
243 if (svr->ecs->bind)
244 {
245 unsigned int nport;
246 char naddr[IF_NAMESIZE];
115 247
116 if (v4) 248 memcpy(&nport, &data[2], 2);
249 svr->proxyport = ntohl(nport);
250
251 if (!inet_ntop(AF_INET, &data[4], naddr, sizeof(naddr))) goto error;
252 svr->proxyip = eina_stringshare_add(naddr);
253 ecore_con_event_proxy_bind(svr);
254 }
255 svr->ecs_state = ECORE_CON_PROXY_STATE_DONE;
256 INF("PROXY CONNECTED");
257 if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
258 svr->ecs_recvbuf = NULL;
259 svr->ecs_buf_offset = svr->ecs_addrlen = 0;
260 memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
261 if (!svr->ssl_state)
262 ecore_con_event_server_add(svr);
263 if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf)))
264 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
265 return;
266error:
267 _ecore_con_server_kill(svr);
268}
269
270static Eina_Bool
271_ecore_con_socks_auth_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5)
272{
273 size_t size;
274 unsigned char *data;
275 switch (v5->method)
276 {
277 case ECORE_CON_SOCKS_V5_METHOD_NONE:
278 svr->ecs_state = ECORE_CON_PROXY_STATE_REQUEST;
279 return EINA_TRUE;
280 case ECORE_CON_SOCKS_V5_METHOD_GSSAPI:
281 return EINA_TRUE;
282 case ECORE_CON_SOCKS_V5_METHOD_USERPASS:
283 if (!v5->username) return EINA_FALSE;
284 if (!v5->password) v5->plen = 1;
285 /* http://tools.ietf.org/html/rfc1929 */
286 size = sizeof(char) * (3 + v5->ulen + v5->plen);
287 data = malloc(size);
288 if (!data) break;
289 data[0] = 1;
290 data[1] = v5->ulen;
291 memcpy(&data[2], v5->username, v5->ulen);
292 data[1 + v5->ulen] = v5->plen;
293 if (v5->password)
294 memcpy(&data[2 + v5->ulen], v5->password, v5->plen);
295 else
296 data[2 + v5->ulen] = 0;
297 svr->ecs_buf = eina_binbuf_manage_new_length(data, size);
298 return EINA_TRUE;
299 default:
300 break;
301 }
302 return EINA_FALSE;
303}
304
305static void
306_ecore_con_socks_read_v5(Ecore_Con_Server *svr, Ecore_Con_Socks_v5 *v5, const unsigned char *buf, unsigned int num)
307{
308 const unsigned char *data;
309
310 DBG("SOCKS: %d bytes", num);
311 switch (svr->ecs_state)
117 { 312 {
118 DBG("SOCKS: %d bytes", num);
119 if (num < 8)
120 {
121 if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new();
122 if (!svr->ecs_recvbuf) goto error;
123 eina_binbuf_append_length(svr->ecs_recvbuf, buf, num);
124 /* the slowest connection on earth */
125 if (eina_binbuf_length_get(svr->ecs_recvbuf) != 8) return;
126 data = eina_binbuf_string_get(svr->ecs_recvbuf);
127 }
128 else if (num > 8) goto error;
129 else
130 data = buf;
131 313
132 /* http://ufasoft.com/doc/socks4_protocol.htm */ 314 case ECORE_CON_PROXY_STATE_READ:
133 if (data[0]) goto error; 315 ECORE_CON_SOCKS_READ(2);
134 switch (data[1]) 316 /* http://en.wikipedia.org/wiki/SOCKS */
317 if (data[0] != 5) goto error;
318 if (data[1] == 0xFF)
319 {
320 ecore_con_event_server_error(svr, "proxy authentication methods rejected");
321 goto error;
322 }
323 v5->method = data[1];
324 if (!_ecore_con_socks_auth_v5(svr, v5)) goto error;
325 if (svr->ecs_state == ECORE_CON_PROXY_STATE_REQUEST)
326 {
327 /* run again to skip auth reading */
328 _ecore_con_socks_read_v5(svr, v5, NULL, 0);
329 return;
330 }
331 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
332 svr->ecs_state = ECORE_CON_PROXY_STATE_AUTH;
333 break;
334 case ECORE_CON_PROXY_STATE_AUTH:
335 ECORE_CON_SOCKS_READ(2);
336 switch (v5->method)
337 {
338 case ECORE_CON_SOCKS_V5_METHOD_NONE:
339 CRIT("HOW DID THIS HAPPEN?????????");
340 goto error;
341 case ECORE_CON_SOCKS_V5_METHOD_GSSAPI:
342 /* TODO: this */
343 break;
344 case ECORE_CON_SOCKS_V5_METHOD_USERPASS:
345 if (data[0] != 1)
346 {
347 ecore_con_event_server_error(svr, "protocol error");
348 goto error; /* wrong version */
349 }
350 if (data[1])
351 {
352 ecore_con_event_server_error(svr, "proxy request authentication rejected");
353 goto error;
354 }
355 default:
356 break;
357 }
358 case ECORE_CON_PROXY_STATE_REQUEST:
135 { 359 {
136 case 90: 360 size_t addrlen, buflen;
137 /* success! */ 361 unsigned char *sbuf;
138 break; 362 addrlen = v5->lookup ? strlen(svr->name) + 1 : (unsigned int)svr->ecs_addrlen;
139 case 91: 363 buflen = sizeof(char) * (6 + addrlen);
140 ecore_con_event_server_error(svr, "proxy request rejected or failed"); 364 sbuf = malloc(buflen);
141 goto error; 365 if (!sbuf)
142 case 92: 366 {
143 ecore_con_event_server_error(svr, "proxying SOCKS server could not perform authentication"); 367 ecore_con_event_server_error(svr, "Memory allocation failure!");
144 goto error; 368 goto error;
145 case 93: 369 }
146 ecore_con_event_server_error(svr, "proxy request authentication rejected"); 370 sbuf[0] = 5;
147 goto error; 371 sbuf[1] = v5->bind ? 2 : 1; /* TODO: 0x03 for UDP port association */
148 default: 372 sbuf[2] = 0;
149 ecore_con_event_server_error(svr, "garbage data from proxy"); 373 if (v5->lookup) /* domain name */
150 goto error; 374 {
375 sbuf[3] = 3;
376 sbuf[4] = addrlen - 1;
377 memcpy(sbuf + 5, svr->name, addrlen - 1);
378 }
379 else
380 {
381 sbuf[3] = (svr->ecs_addrlen == 4) ? 1 : 4;
382 memcpy(sbuf + 4, svr->ecs_addr, addrlen);
383 }
384 sbuf[addrlen + 4] = svr->port >> 8;
385 sbuf[addrlen + 5] = svr->port & 0xff;
386
387 svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen);
388 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
389 break;
151 } 390 }
152 if (svr->ecs->bind) 391 case ECORE_CON_PROXY_STATE_CONFIRM:
153 { 392 {
154 unsigned int nport; 393 /* this is ugly because we have to read an exact number of bytes,
155 char naddr[IF_NAMESIZE]; 394 * but we don't know what that number is until we've already read
156 395 * at least 5 bytes to determine the length of the unknown stream.
157 memcpy(&nport, &data[2], 2); 396 * yep.
158 svr->proxyport = ntohl(nport); 397 */
159 398 size_t to_read, len = svr->ecs_recvbuf ? eina_binbuf_length_get(svr->ecs_recvbuf) : 0;
160 if (!inet_ntop(AF_INET, &data[4], naddr, sizeof(naddr))) goto error; 399 if (num + len < 5)
161 svr->proxyip = eina_stringshare_add(naddr); 400 {
162 ecore_con_event_proxy_bind(svr); 401 /* guarantees we get called again */
402 ECORE_CON_SOCKS_READ(5);
403 }
404 if (len >= 5)
405 {
406 data = eina_binbuf_string_get(svr->ecs_recvbuf);
407 data += 3;
408 }
409 else
410 data = buf + 3 - len;
411 switch (data[0])
412 {
413 case 1:
414 to_read = 4;
415 break;
416 case 3:
417 to_read = data[1] + 1;
418 break;
419 case 4:
420 to_read = 16;
421 /* lazy debugging stub comment */
422 break;
423 default:
424 ecore_con_event_server_error(svr, "protocol error");
425 goto error;
426 }
427 /* at this point, we finally know exactly how much we need to read */
428 ECORE_CON_SOCKS_READ(6 + to_read);
429
430 if (data[0] != 5)
431 {
432 ecore_con_event_server_error(svr, "protocol error");
433 goto error; /* wrong version */
434 }
435 switch (data[1])
436 {
437 case 0:
438 break;
439 case 1:
440 ecore_con_event_server_error(svr, "general proxy failure");
441 goto error;
442 case 2:
443 ecore_con_event_server_error(svr, "connection not allowed by ruleset");
444 goto error;
445 case 3:
446 ecore_con_event_server_error(svr, "network unreachable");
447 goto error;
448 case 4:
449 ecore_con_event_server_error(svr, "host unreachable");
450 goto error;
451 case 5:
452 ecore_con_event_server_error(svr, "connection refused by destination host");
453 goto error;
454 case 6:
455 ecore_con_event_server_error(svr, "TTL expired");
456 goto error;
457 case 7:
458 ecore_con_event_server_error(svr, "command not supported / protocol error");
459 goto error;
460 case 8:
461 ecore_con_event_server_error(svr, "address type not supported");
462 default:
463 goto error;
464 }
465 if (data[2])
466 {
467 ecore_con_event_server_error(svr, "protocol error");
468 goto error;
469 }
470 memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
471 if (!svr->ssl_state)
472 ecore_con_event_server_add(svr);
473 if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf)))
474 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
475 svr->ecs_buf_offset = svr->ecs_addrlen = 0;
476 svr->ecs_state = ECORE_CON_PROXY_STATE_DONE;
477 INF("PROXY CONNECTED");
478 break;
163 } 479 }
164 svr->ecs_state = ECORE_CON_SOCKS_STATE_DONE; 480 default:
165 INF("PROXY CONNECTED"); 481 break;
166 if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
167 svr->ecs_recvbuf = NULL;
168 svr->ecs_buf_offset = svr->ecs_addrlen = 0;
169 memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
170 if (!svr->ssl_state)
171 ecore_con_event_server_add(svr);
172 if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf)))
173 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
174 } 482 }
483 if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
484 svr->ecs_recvbuf = NULL;
485
175 return; 486 return;
176error: 487error:
177 _ecore_con_server_kill(svr); 488 _ecore_con_server_kill(svr);
178} 489}
179 490
491/////////////////////////////////////////////////////////////////////////////////////
492void
493ecore_con_socks_shutdown(void)
494{
495 Ecore_Con_Socks *ecs;
496 EINA_LIST_FREE(ecore_con_socks_proxies, ecs)
497 _ecore_con_socks_free(ecs);
498 _ecore_con_proxy_once = NULL;
499 _ecore_con_proxy_global = NULL;
500}
501
502void
503ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num)
504{
505 ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return;
506
507 if (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) return;
508
509 if (v4) _ecore_con_socks_read_v4(svr, v4, buf, (unsigned int)num);
510 else _ecore_con_socks_read_v5(svr, v5, buf, (unsigned int)num);
511}
512
180Eina_Bool 513Eina_Bool
181ecore_con_socks_svr_init(Ecore_Con_Server *svr) 514ecore_con_socks_svr_init(Ecore_Con_Server *svr)
182{ 515{
183 unsigned char *sbuf;
184 ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return EINA_FALSE; 516 ECORE_CON_SOCKS_CAST_ELSE(svr->ecs) return EINA_FALSE;
185 517
186 if (!svr->ip) return EINA_FALSE; 518 if (!svr->ip) return EINA_FALSE;
187 if (svr->ecs_buf) return EINA_FALSE; 519 if (svr->ecs_buf) return EINA_FALSE;
188 if (svr->ecs_state != ECORE_CON_SOCKS_STATE_INIT) return EINA_FALSE; 520 if (svr->ecs_state != ECORE_CON_PROXY_STATE_INIT) return EINA_FALSE;
189 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); 521 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
190 if (v4) 522 if (v4) return _ecore_con_socks_svr_init_v4(svr, v4);
191 { 523 return _ecore_con_socks_svr_init_v5(svr, v5);
192 size_t addrlen, buflen, ulen = 1;
193 addrlen = svr->ecs->lookup ? strlen(svr->name) + 1: 0;
194 if (svr->ecs->username) ulen += strlen(svr->ecs->username);
195 buflen = sizeof(char) * (8 + ulen + addrlen);
196 sbuf = malloc(buflen);
197 if (!sbuf)
198 {
199 ecore_con_event_server_error(svr, "Memory allocation failure!");
200 _ecore_con_server_kill(svr);
201 return EINA_FALSE;
202 }
203 /* http://en.wikipedia.org/wiki/SOCKS */
204 sbuf[0] = 4;
205 sbuf[1] = v4->bind ? 2 : 1;
206 sbuf[2] = svr->port >> 8;
207 sbuf[3] = svr->port & 0xff;
208 if (addrlen)
209 {
210 sbuf[4] = sbuf[5] = sbuf[6] = 0;
211 sbuf[7] = 1;
212 }
213 else
214 memcpy(sbuf + 4, svr->ecs_addr, 4);
215 if (svr->ecs->username)
216 memcpy(sbuf + 8, svr->ecs->username, ulen);
217 else
218 sbuf[8] = 0;
219 if (addrlen) memcpy(sbuf + 8 + ulen, svr->name, addrlen);
220
221 svr->ecs_buf = eina_binbuf_manage_new_length(sbuf, buflen);
222 }
223 return EINA_TRUE;
224} 524}
225 525
226void 526void
227ecore_con_socks_dns_cb(const char *canonname __UNUSED__, const char *ip, struct sockaddr *addr, int addrlen, Ecore_Con_Server *svr) 527ecore_con_socks_dns_cb(const char *canonname __UNUSED__, const char *ip, struct sockaddr *addr, int addrlen __UNUSED__, Ecore_Con_Server *svr)
228{ 528{
229 svr->ip = eina_stringshare_add(ip); 529 svr->ip = eina_stringshare_add(ip);
230 svr->ecs_addrlen = addrlen;
231 svr->ecs_state++; 530 svr->ecs_state++;
232 if (addr->sa_family == AF_INET) 531 if (addr->sa_family == AF_INET)
233 memcpy(svr->ecs_addr, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); 532 {
533 memcpy(svr->ecs_addr, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4);
534 svr->ecs_addrlen = 4;
535 }
234#ifdef HAVE_IPV6 536#ifdef HAVE_IPV6
235 else 537 else
236 memcpy(svr->ecs_addr, &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, addrlen); 538 {
539 memcpy(svr->ecs_addr, &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, 16);
540 svr->ecs_addrlen = 16;
541 }
237#endif 542#endif
238 ecore_con_socks_svr_init(svr); 543 ecore_con_socks_svr_init(svr);
239} 544}
@@ -242,36 +547,57 @@ void
242ecore_con_socks_init(void) 547ecore_con_socks_init(void)
243{ 548{
244 const char *socks; 549 const char *socks;
245 char *u, *h, *p, *l; 550 char *h, *p, *l, *u = NULL;
246 char buf[64]; 551 char buf[512];
247 int port, lookup = 0; 552 int port, lookup = 0;
553 Eina_Bool v5 = EINA_FALSE;
248 Ecore_Con_Socks *ecs; 554 Ecore_Con_Socks *ecs;
249 unsigned char addr[sizeof(struct in_addr)]; 555 unsigned char addr[sizeof(struct in_addr)];
556#ifdef HAVE_IPV6
557 unsigned char addr6[sizeof(struct in6_addr)];
558#endif
250 559
251 /* ECORE_CON_SOCKS_V4=user@host:port:[1|0] */ 560 /* ECORE_CON_SOCKS_V4=[user@]host:port-[1|0] */
252 socks = getenv("ECORE_CON_SOCKS_V4"); 561 socks = getenv("ECORE_CON_SOCKS_V4");
253 if ((!socks) || (!socks[0]) || (strlen(socks) > 64)) return; 562 if (!socks)
563 {
564 /* ECORE_CON_SOCKS_V5=[user@]host-port:[1|0] */
565 socks = getenv("ECORE_CON_SOCKS_V5");
566 v5 = EINA_TRUE;
567 }
568 if ((!socks) || (!socks[0]) || (strlen(socks) > 512)) return;
254 strncpy(buf, socks, sizeof(buf)); 569 strncpy(buf, socks, sizeof(buf));
255 h = strchr(buf, '@'); 570 h = strchr(buf, '@');
256 u = NULL;
257 /* username */ 571 /* username */
258 if (h && (h - buf > 0)) *h++ = 0, u = buf; 572 if (h && (h - buf > 0)) *h++ = 0, u = buf;
259 else h = buf; 573 else h = buf;
260 574
261 /* host ip; I ain't resolvin shit here */ 575 /* host ip; I ain't resolvin shit here */
262 p = strchr(h, ':'); 576 p = strchr(h, '-');
263 if (!p) return; 577 if (!p) return;
264 *p++ = 0; 578 *p++ = 0;
265 if (!inet_pton(AF_INET, h, addr)) return; 579 if (!inet_pton(AF_INET, h, addr))
580#ifdef HAVE_IPV6
581 {
582 if (!v5) return;
583 if (!inet_pton(AF_INET6, h, addr6))
584 return;
585 }
586#else
587 return;
588#endif
266 589
267 errno = 0; 590 errno = 0;
268 port = strtol(p, &l, 10); 591 port = strtol(p, &l, 10);
269 if (errno || (port < 0) || (port > 65535)) return; 592 if (errno || (port < 0) || (port > 65535)) return;
270 if (l && (l[0] == ':')) 593 if (l && (l[0] == ':'))
271 lookup = (l[1] == '1'); 594 lookup = (l[1] == '1');
272 ecs = ecore_con_socks4_remote_add(h, port, u); 595 if (v5)
596 ecs = ecore_con_socks5_remote_add(h, port, u, NULL);
597 else
598 ecs = ecore_con_socks4_remote_add(h, port, u);
273 if (!ecs) return; 599 if (!ecs) return;
274 ecore_con_socks4_lookup_set(ecs, lookup); 600 ecore_con_socks_lookup_set(ecs, lookup);
275 ecore_con_socks_apply_always(ecs); 601 ecore_con_socks_apply_always(ecs);
276 INF("Added global proxy server %s%s%s:%d - DNS lookup %s", 602 INF("Added global proxy server %s%s%s:%d - DNS lookup %s",
277 u ?: "", u ? "@" : "", h, port, lookup ? "ENABLED" : "DISABLED"); 603 u ?: "", u ? "@" : "", h, port, lookup ? "ENABLED" : "DISABLED");
@@ -300,10 +626,17 @@ EAPI Ecore_Con_Socks *
300ecore_con_socks4_remote_add(const char *ip, int port, const char *username) 626ecore_con_socks4_remote_add(const char *ip, int port, const char *username)
301{ 627{
302 Ecore_Con_Socks *ecs; 628 Ecore_Con_Socks *ecs;
629 size_t ulen = 0;
303 630
304 if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL; 631 if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL;
305 632
306 ecs = _ecore_con_socks_find(4, ip, port, username); 633 if (username)
634 {
635 ulen = strlen(username);
636 /* max length for protocol */
637 if ((!ulen) || (ulen > 255)) return NULL;
638 }
639 ecs = _ecore_con_socks_find(4, ip, port, username, ulen, NULL, 0);
307 if (ecs) return ecs; 640 if (ecs) return ecs;
308 641
309 ecs = calloc(1, sizeof(Ecore_Con_Socks_v4)); 642 ecs = calloc(1, sizeof(Ecore_Con_Socks_v4));
@@ -313,92 +646,194 @@ ecore_con_socks4_remote_add(const char *ip, int port, const char *username)
313 ecs->ip = eina_stringshare_add(ip); 646 ecs->ip = eina_stringshare_add(ip);
314 ecs->port = port; 647 ecs->port = port;
315 ecs->username = eina_stringshare_add(username); 648 ecs->username = eina_stringshare_add(username);
649 ecs->ulen = ulen;
316 ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs); 650 ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs);
317 return ecs; 651 return ecs;
318} 652}
319 653
320/** 654/**
321 * Set DNS lookup mode on an existing SOCKS v4 proxy 655 * Find a SOCKS v4 proxy in the proxy list
322 * 656 *
323 * According to RFC, SOCKS v4 does not require that a proxy perform 657 * Use this to determine if a SOCKS proxy was previously added by checking
324 * its own DNS lookups for addresses. SOCKS v4a specifies the protocol 658 * the proxy list against the parameters given.
325 * for this. If you want to enable remote DNS lookup and are sure that your 659 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.)
326 * proxy supports it, use this function. 660 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip
327 * @param ecs The proxy object 661 * @param username The username used for the proxy (OPTIONAL)
328 * @param enable If true, the proxy will perform the dns lookup 662 * @return true only if a proxy exists matching the given params
329 * @note By default, this setting is DISABLED. 663 * @note This function matches slightly more loosely than ecore_con_socks4_remote_add(), and
664 * ecore_con_socks4_remote_add() should be used to return the actual object.
330 * @since 1.2 665 * @since 1.2
331 */ 666 */
332EAPI void 667EAPI Eina_Bool
333ecore_con_socks4_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable) 668ecore_con_socks4_remote_exists(const char *ip, int port, const char *username)
334{ 669{
335 ECORE_CON_SOCKS_CAST_ELSE(ecs) return; 670 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0])))
336 if (v4) v4->lookup = !!enable; 671 return EINA_FALSE;
672 return !!_ecore_con_socks_find(4, ip, port, username, username ? strlen(username) : 0, NULL, 0);
337} 673}
338 674
339/** 675/**
340 * Get DNS lookup mode on an existing SOCKS v4 proxy 676 * Remove a SOCKS v4 proxy from the proxy list and delete it
341 * 677 *
342 * According to RFC, SOCKS v4 does not require that a proxy perform 678 * Use this to remove a SOCKS proxy from the proxy list by checking
343 * its own DNS lookups for addresses. SOCKS v4a specifies the protocol 679 * the list against the parameters given. The proxy will then be deleted.
344 * for this. This function returns whether lookups are enabled on a proxy object. 680 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.)
345 * @param ecs The proxy object 681 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip
346 * @return If true, the proxy will perform the dns lookup 682 * @param username The username used for the proxy (OPTIONAL)
347 * @note By default, this setting is DISABLED. 683 * @note This function matches in the same way as ecore_con_socks4_remote_exists().
684 * @warning Be aware that deleting a proxy which is being used WILL ruin your life.
348 * @since 1.2 685 * @since 1.2
349 */ 686 */
350EAPI Eina_Bool 687EAPI void
351ecore_con_socks4_lookup_get(Ecore_Con_Socks *ecs) 688ecore_con_socks4_remote_del(const char *ip, int port, const char *username)
352{ 689{
353 ECORE_CON_SOCKS_CAST_ELSE(ecs) return EINA_FALSE; 690 Ecore_Con_Socks_v4 *v4;
354 return v4 ? v4->lookup : EINA_FALSE; 691
692 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) return;
693 if (!ecore_con_socks_proxies) return;
694
695 v4 = (Ecore_Con_Socks_v4*)_ecore_con_socks_find(4, ip, port, username, username ? strlen(username) : 0, NULL, 0);
696 if (!v4) return;
697 ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v4);
698 _ecore_con_socks_free((Ecore_Con_Socks*)v4);
699}
700/**
701 * Add a SOCKS v5 proxy to the proxy list
702 *
703 * Use this to create (or return, if previously added) a SOCKS proxy
704 * object which can be used by any ecore_con servers.
705 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.)
706 * @param port The port to connect to on the proxy
707 * @param username The username to use for the proxy (OPTIONAL)
708 * @param password The password to use for the proxy (OPTIONAL)
709 * @return An allocated proxy object, or NULL on failure
710 * @note This object NEVER needs to be explicitly freed.
711 * @since 1.2
712 */
713EAPI Ecore_Con_Socks *
714ecore_con_socks5_remote_add(const char *ip, int port, const char *username, const char *password)
715{
716 Ecore_Con_Socks_v5 *ecs5;
717 size_t ulen = 0, plen = 0;
718
719 if ((!ip) || (!ip[0]) || (port < 0) || (port > 65535)) return NULL;
720
721 if (username)
722 {
723 ulen = strlen(username);
724 /* max length for protocol */
725 if ((!ulen) || (ulen > 255)) return NULL;
726 }
727 if (password)
728 {
729 plen = strlen(password);
730 /* max length for protocol */
731 if ((!plen) || (plen > 255)) return NULL;
732 }
733 ecs5 = (Ecore_Con_Socks_v5*)_ecore_con_socks_find(5, ip, port, username, ulen, password, plen);
734 if (ecs5) return (Ecore_Con_Socks*)ecs5;
735
736 ecs5 = calloc(1, sizeof(Ecore_Con_Socks_v5));
737 if (!ecs5) return NULL;
738
739 ecs5->version = 5;
740 ecs5->ip = eina_stringshare_add(ip);
741 ecs5->port = port;
742 ecs5->username = eina_stringshare_add(username);
743 ecs5->ulen = ulen;
744 ecs5->password = eina_stringshare_add(password);
745 ecs5->plen = plen;
746 ecore_con_socks_proxies = eina_list_append(ecore_con_socks_proxies, ecs5);
747 return (Ecore_Con_Socks*)ecs5;
355} 748}
356 749
357/** 750/**
358 * Find a SOCKS v4 proxy in the proxy list 751 * Find a SOCKS v5 proxy in the proxy list
359 * 752 *
360 * Use this to determine if a SOCKS proxy was previously added by checking 753 * Use this to determine if a SOCKS proxy was previously added by checking
361 * the proxy list against the parameters given. 754 * the proxy list against the parameters given.
362 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) 755 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.)
363 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip 756 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip
364 * @param username The username used for the proxy (OPTIONAL) 757 * @param username The username used for the proxy (OPTIONAL)
758 * @param password The password used for the proxy (OPTIONAL)
365 * @return true only if a proxy exists matching the given params 759 * @return true only if a proxy exists matching the given params
366 * @note This function matches slightly more loosely than ecore_con_socks4_remote_add(), and 760 * @note This function matches slightly more loosely than ecore_con_socks5_remote_add(), and
367 * ecore_con_socks4_remote_add() should be used to return the actual object. 761 * ecore_con_socks5_remote_add() should be used to return the actual object.
368 * @since 1.2 762 * @since 1.2
369 */ 763 */
370EAPI Eina_Bool 764EAPI Eina_Bool
371ecore_con_socks4_remote_exists(const char *ip, int port, const char *username) 765ecore_con_socks5_remote_exists(const char *ip, int port, const char *username, const char *password)
372{ 766{
373 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) 767 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0])) || (password && (!password[0])))
374 return EINA_FALSE; 768 return EINA_FALSE;
375 return !!_ecore_con_socks_find(4, ip, port, username); 769 return !!_ecore_con_socks_find(5, ip, port, username, username ? strlen(username) : 0, password, password ? strlen(password) : 0);
376} 770}
377 771
378/** 772/**
379 * Remove a SOCKS v4 proxy from the proxy list and delete it 773 * Remove a SOCKS v5 proxy from the proxy list and delete it
380 * 774 *
381 * Use this to remove a SOCKS proxy from the proxy list by checking 775 * Use this to remove a SOCKS proxy from the proxy list by checking
382 * the list against the parameters given. The proxy will then be deleted. 776 * the list against the parameters given. The proxy will then be deleted.
383 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.) 777 * @param ip The ip address of the proxy (NOT DOMAIN NAME. IP ADDRESS.)
384 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip 778 * @param port The port to connect to on the proxy, or -1 to match the first proxy with @p ip
385 * @param username The username used for the proxy (OPTIONAL) 779 * @param username The username used for the proxy (OPTIONAL)
780 * @param password The password used for the proxy (OPTIONAL)
386 * @note This function matches in the same way as ecore_con_socks4_remote_exists(). 781 * @note This function matches in the same way as ecore_con_socks4_remote_exists().
387 * @warning Be aware that deleting a proxy which is being used WILL ruin your life. 782 * @warning Be aware that deleting a proxy which is being used WILL ruin your life.
388 * @since 1.2 783 * @since 1.2
389 */ 784 */
390EAPI void 785EAPI void
391ecore_con_socks4_remote_del(const char *ip, int port, const char *username) 786ecore_con_socks5_remote_del(const char *ip, int port, const char *username, const char *password)
392{ 787{
393 Ecore_Con_Socks_v4 *v4; 788 Ecore_Con_Socks_v5 *v5;
394 789
395 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0]))) return; 790 if ((!ip) || (!ip[0]) || (port < -1) || (port > 65535) || (username && (!username[0])) || (password && (!password[0])))
791 return;
396 if (!ecore_con_socks_proxies) return; 792 if (!ecore_con_socks_proxies) return;
397 793
398 v4 = (Ecore_Con_Socks_v4*)_ecore_con_socks_find(4, ip, port, username); 794 v5 = (Ecore_Con_Socks_v5*)_ecore_con_socks_find(5, ip, port, username, username ? strlen(username) : 0, password, password ? strlen(password) : 0);
399 if (!v4) return; 795 if (!v5) return;
400 ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v4); 796 ecore_con_socks_proxies = eina_list_remove(ecore_con_socks_proxies, v5);
401 _ecore_con_socks_free((Ecore_Con_Socks*)v4); 797 _ecore_con_socks_free((Ecore_Con_Socks*)v5);
798}
799
800/**
801 * Set DNS lookup mode on an existing SOCKS proxy
802 *
803 * According to RFC, SOCKS v4 does not require that a proxy perform
804 * its own DNS lookups for addresses. SOCKS v4a specifies the protocol
805 * for this. SOCKS v5 allows DNS lookups.
806 * If you want to enable remote DNS lookup and are sure that your
807 * proxy supports it, use this function.
808 * @param ecs The proxy object
809 * @param enable If true, the proxy will perform the dns lookup
810 * @note By default, this setting is DISABLED.
811 * @since 1.2
812 */
813EAPI void
814ecore_con_socks_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable)
815{
816 ECORE_CON_SOCKS_CAST_ELSE(ecs) return;
817 ecs->lookup = !!enable;
818}
819
820/**
821 * Get DNS lookup mode on an existing SOCKS proxy
822 *
823 * According to RFC, SOCKS v4 does not require that a proxy perform
824 * its own DNS lookups for addresses. SOCKS v4a specifies the protocol
825 * for this. SOCKS v5 allows DNS lookups.
826 * This function returns whether lookups are enabled on a proxy object.
827 * @param ecs The proxy object
828 * @return If true, the proxy will perform the dns lookup
829 * @note By default, this setting is DISABLED.
830 * @since 1.2
831 */
832EAPI Eina_Bool
833ecore_con_socks_lookup_get(Ecore_Con_Socks *ecs)
834{
835 ECORE_CON_SOCKS_CAST_ELSE(ecs) return EINA_FALSE;
836 return ecs->lookup;
402} 837}
403 838
404/** 839/**
@@ -434,6 +869,14 @@ ecore_con_socks_bind_get(Ecore_Con_Socks *ecs)
434 return ecs->bind; 869 return ecs->bind;
435} 870}
436 871
872/**
873 * Return SOCKS version of a SOCKS proxy
874 *
875 * Use this function to return the SOCKS protocol version of a proxy
876 * @param ecs The proxy object
877 * @return 0 on error, else 4/5
878 * @since 1.2
879 */
437EAPI unsigned int 880EAPI unsigned int
438ecore_con_socks_version_get(Ecore_Con_Socks *ecs) 881ecore_con_socks_version_get(Ecore_Con_Socks *ecs)
439{ 882{
@@ -482,7 +925,8 @@ ecore_con_socks_apply_once(Ecore_Con_Socks *ecs)
482 * @see ecore_con_socks_apply_once() 925 * @see ecore_con_socks_apply_once()
483 * @since 1.2 926 * @since 1.2
484 * @note ecore-con supports setting this through environment variables like so: 927 * @note ecore-con supports setting this through environment variables like so:
485 * ECORE_CON_SOCKS_V4=[user@]server:port:lookup 928 * ECORE_CON_SOCKS_V4=[user@]server-port:lookup
929 * ECORE_CON_SOCKS_V5=[user@]server-port:lookup
486 * user is the OPTIONAL string that would be passed to the proxy as the username 930 * user is the OPTIONAL string that would be passed to the proxy as the username
487 * server is the IP_ADDRESS of the proxy server 931 * server is the IP_ADDRESS of the proxy server
488 * port is the port to connect to on the proxy server 932 * port is the port to connect to on the proxy server
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c
index 6104632..cd8b9c6 100644
--- a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c
@@ -652,6 +652,7 @@ ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr)
652 * Use this function to add a SSL PEM certificate. 652 * Use this function to add a SSL PEM certificate.
653 * Simply specify the cert here to use it in the server object for connecting or listening. 653 * Simply specify the cert here to use it in the server object for connecting or listening.
654 * If there is an error loading the certificate, an error will automatically be logged. 654 * If there is an error loading the certificate, an error will automatically be logged.
655 * @param svr The server object
655 * @param cert The path to the certificate. 656 * @param cert The path to the certificate.
656 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. 657 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE.
657 */ 658 */
@@ -683,6 +684,7 @@ ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr,
683 * Use this function to add a SSL PEM CA file. 684 * Use this function to add a SSL PEM CA file.
684 * Simply specify the file here to use it in the server object for connecting or listening. 685 * Simply specify the file here to use it in the server object for connecting or listening.
685 * If there is an error loading the CAs, an error will automatically be logged. 686 * If there is an error loading the CAs, an error will automatically be logged.
687 * @param svr The server object
686 * @param ca_file The path to the CA file. 688 * @param ca_file The path to the CA file.
687 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE. 689 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE.
688 * @note since 1.2, this function can load directores 690 * @note since 1.2, this function can load directores
@@ -747,6 +749,7 @@ ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr,
747 * Use this function to add a SSL PEM CRL file 749 * Use this function to add a SSL PEM CRL file
748 * Simply specify the CRL file here to use it in the server object for connecting or listening. 750 * Simply specify the CRL file here to use it in the server object for connecting or listening.
749 * If there is an error loading the CRL, an error will automatically be logged. 751 * If there is an error loading the CRL, an error will automatically be logged.
752 * @param svr The server object
750 * @param crl_file The path to the CRL file. 753 * @param crl_file The path to the CRL file.
751 * @return EINA_FALSE if the file cannot be loaded, 754 * @return EINA_FALSE if the file cannot be loaded,
752 * otherwise EINA_TRUE. 755 * otherwise EINA_TRUE.
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