summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-07 13:34:28 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-12-10 08:44:06 -0200
commitf4306d654dc55e8a0449698da18f371644d656df (patch)
tree0fc90508f30cb10bb0a1d6e7e1bf942d97bfc23e
parent72ad2c5eb7fbe8ceb491d1f545f82ae7cfc5457b (diff)
downloadefl-devs/barbieri/ecore_con-efl_net.tar.gz
ecore_con: Ecore_Con_Server now on top of Efl_Net!devs/barbieri/ecore_con-efl_net
This is a major work and unfortunately couldn't be split into smaller pieces as old code was highly coupled. Ecore_Con_Server is now a wrapper around Efl_Net_Dialer_Simple (ecore_con_server_connect()) and Efl_Net_Server_Simple (ecore_con_server_add()), doing all that the original version did with some fixes so ecore_con_ssl_server_upgrade() and ecore_con_ssl_client_upgrade() are more usable -- see the examples and -t/--type=tcp+ssl. I tried to be bug-compatible, with code annotations where things doesn't make sense. This was based on ecore_con_suite tests and some manual experimenting with the examples, these can be helpful if you find regressions (report/assign to me).
-rw-r--r--src/Makefile_Ecore_Con.am15
-rw-r--r--src/lib/ecore_con/Ecore_Con.h130
-rw-r--r--src/lib/ecore_con/Ecore_Con_Eo.h5
-rw-r--r--src/lib/ecore_con/Ecore_Con_Legacy.h29
-rw-r--r--src/lib/ecore_con/ecore_con.c2862
-rw-r--r--src/lib/ecore_con/ecore_con_alloc.c4
-rw-r--r--src/lib/ecore_con/ecore_con_eet.c5
-rw-r--r--src/lib/ecore_con/ecore_con_eet_base.eo5
-rw-r--r--src/lib/ecore_con/ecore_con_info.c297
-rw-r--r--src/lib/ecore_con/ecore_con_legacy.c2515
-rw-r--r--src/lib/ecore_con/ecore_con_local.c301
-rw-r--r--src/lib/ecore_con/ecore_con_private.h297
-rw-r--r--src/lib/ecore_con/ecore_con_socks.c488
-rw-r--r--src/lib/ecore_con/ecore_con_ssl.c1963
-rw-r--r--src/lib/ecore_con/efl_network.eo201
-rw-r--r--src/lib/ecore_con/efl_network_client.eo30
-rw-r--r--src/lib/ecore_con/efl_network_connector.eo8
-rw-r--r--src/lib/ecore_con/efl_network_server.eo93
18 files changed, 2670 insertions, 6578 deletions
diff --git a/src/Makefile_Ecore_Con.am b/src/Makefile_Ecore_Con.am
index c3e51ae441..1fc3ea5441 100644
--- a/src/Makefile_Ecore_Con.am
+++ b/src/Makefile_Ecore_Con.am
@@ -2,10 +2,6 @@
### Library
ecore_con_eolian_files = \
- lib/ecore_con/efl_network.eo \
- lib/ecore_con/efl_network_client.eo \
- lib/ecore_con/efl_network_server.eo \
- lib/ecore_con/efl_network_connector.eo \
lib/ecore_con/efl_net_socket.eo \
lib/ecore_con/efl_net_socket_simple.eo \
lib/ecore_con/efl_net_socket_fd.eo \
@@ -71,7 +67,6 @@ lib_LTLIBRARIES += lib/ecore_con/libecore_con.la
installed_ecoreconmainheadersdir = $(includedir)/ecore-con-@VMAJ@
dist_installed_ecoreconmainheaders_DATA = \
lib/ecore_con/Ecore_Con.h \
-lib/ecore_con/Ecore_Con_Legacy.h \
lib/ecore_con/Ecore_Con_Eo.h \
lib/ecore_con/Ecore_Con_Eet.h \
lib/ecore_con/Ecore_Con_Eet_Legacy.h \
@@ -83,16 +78,15 @@ nodist_installed_ecoreconmainheaders_DATA = \
lib_ecore_con_libecore_con_la_SOURCES = \
lib/ecore_con/ecore_con_alloc.c \
lib/ecore_con/ecore_con.c \
+lib/ecore_con/ecore_con_legacy.c \
lib/ecore_con/ecore_con_eet.c \
lib/ecore_con/ecore_con_socks.c \
-lib/ecore_con/ecore_con_ssl.c \
lib/ecore_con/ecore_con_url.c \
lib/ecore_con/ecore_con_url_curl.c \
lib/ecore_con/ecore_con_url_curl.h \
static_libs/http-parser/http_parser.c \
static_libs/http-parser/http_parser.h \
lib/ecore_con/ecore_con_private.h \
-lib/ecore_con/ecore_con_info.c \
lib/ecore_con/efl_net_socket.c \
lib/ecore_con/efl_net_socket_simple.c \
lib/ecore_con/efl_net_socket_fd.c \
@@ -113,7 +107,8 @@ lib/ecore_con/efl_net_server_udp_client.c \
lib/ecore_con/efl_net_socket_ssl.c \
lib/ecore_con/efl_net_ssl_context.c \
lib/ecore_con/efl_net_dialer_ssl.c \
-lib/ecore_con/efl_net_server_ssl.c
+lib/ecore_con/efl_net_server_ssl.c \
+lib/ecore_con/ecore_con_local.c
if EFL_NET_CONTROL_BACKEND_CONNMAN
lib_ecore_con_libecore_con_la_SOURCES += \
@@ -146,9 +141,9 @@ lib/ecore_con/efl_net_ssl_ctx-gnutls.c \
lib/ecore_con/efl_net_ssl_ctx-none.c
if HAVE_WINDOWS
-lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local_win32.c
+#lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local_win32.c
else
-lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local.c \
+lib_ecore_con_libecore_con_la_SOURCES += \
lib/ecore_con/efl_net_socket_unix.c \
lib/ecore_con/efl_net_dialer_unix.c \
lib/ecore_con/efl_net_server_unix.c
diff --git a/src/lib/ecore_con/Ecore_Con.h b/src/lib/ecore_con/Ecore_Con.h
index 393b94c825..e8592f9580 100644
--- a/src/lib/ecore_con/Ecore_Con.h
+++ b/src/lib/ecore_con/Ecore_Con.h
@@ -227,7 +227,41 @@ extern "C" {
#define ECORE_CON_USE_SSL ECORE_CON_USE_SSL2
#define ECORE_CON_REMOTE_SYSTEM ECORE_CON_REMOTE_TCP
-typedef Eo Ecore_Con;
+/** Types for an ecore_con client/server object. A correct way to set this
+ * type is with an ECORE_CON_$TYPE, optionally OR'ed with an ECORE_CON_$USE if
+ * encryption is desired, and LOAD_CERT if the previously loaded certificate
+ * should be used.
+ *
+ * @ingroup Ecore_Con
+ */
+typedef enum
+{
+ ECORE_CON_LOCAL_USER = 0, /** Socket in "~/.ecore" */
+ ECORE_CON_LOCAL_SYSTEM = 1, /** Socket in /tmp */
+ ECORE_CON_LOCAL_ABSTRACT = 2, /** Abstract socket */
+ ECORE_CON_REMOTE_TCP = 3, /** Remote server using TCP */
+ ECORE_CON_REMOTE_MCAST = 4, /** Remote multicast UDP server (ecore_con_server_add() only) */
+ ECORE_CON_REMOTE_UDP = 5, /** Remote server using UDP */
+ ECORE_CON_REMOTE_BROADCAST = 6, /** Remote broadcast using UDP (ecore_con_server_connect() only) */
+ ECORE_CON_REMOTE_NODELAY = 7, /** Remote TCP connection sending packets
+ * immediately */
+ ECORE_CON_REMOTE_CORK = 8, /** Remote TCP connection sending data in large chunks
+ * Note: Only available on Linux
+ *
+ * @since 1.2 */
+ ECORE_CON_USE_SSL2 = 16 /* 1 << 4 */, /** Use SSL2: UNSUPPORTED. */
+ ECORE_CON_USE_SSL3 = 32 /* 1 << 5 */, /** Use SSL3: UNSUPPORTED. */
+ ECORE_CON_USE_TLS = 64 /* 1 << 6 */, /** Use TLS */
+ ECORE_CON_USE_MIXED = 96 /* Ecore.Con.Type.use_tls | Ecore.Con.Type.use_ssl3 */, /** Use both TLS and SSL3 */
+ ECORE_CON_LOAD_CERT = 128 /* 1 << 7 */, /** Attempt to use the loaded
+ * certificate */
+ ECORE_CON_NO_PROXY = 256 /* 1 << 8 */, /** Disable all types of proxy on the
+ * server Note: Only functional for
+ * clients
+ *
+ * @since 1.2 */
+ ECORE_CON_SOCKET_ACTIVATE = 512 /* 1 << 9 */
+} Ecore_Con_Type;
/**
* @typedef Ecore_Con_Socks
@@ -265,13 +299,38 @@ typedef void (*Ecore_Con_Dns_Cb)(const char *canonname,
/** @} */
-#ifndef EFL_NOLEGACY_API_SUPPORT
-#include "Ecore_Con_Legacy.h"
-#endif
#ifdef EFL_BETA_API_SUPPORT
#include "Ecore_Con_Eo.h"
#endif
+/**
+ * @struct _Ecore_Con_Server
+ * Used to provide legacy ABI/ABI compatibility with non-Eo applications.
+ * @ingroup Ecore_Con_Server_Group
+ */
+struct _Ecore_Con_Server;
+
+/**
+ * @typedef Ecore_Con_Server
+ * Used to provide legacy API/ABI compatibility with non-Eo applications.
+ * @ingroup Ecore_Con_Server_Group
+ */
+typedef struct _Ecore_Con_Server Ecore_Con_Server;
+
+/**
+ * @struct _Ecore_Con_Client
+ * Used to provide legacy ABI/ABI compatibility with non-Eo applications.
+ * @ingroup Ecore_Con_Client_Group
+ */
+struct _Ecore_Con_Client;
+
+/**
+ * @typedef Ecore_Con_Client
+ * Used to provide legacy API/ABI compatibility with non-Eo applications.
+ * @ingroup Ecore_Con_Client_Group
+ */
+typedef struct _Ecore_Con_Client Ecore_Con_Client;
+
/**
* @struct _Ecore_Con_Url
@@ -651,6 +710,26 @@ EAPI int ecore_con_init(void);
EAPI int ecore_con_shutdown(void);
/**
+ * @brief Do an asynchronous DNS lookup.
+ *
+ * This function performs a DNS lookup on the hostname specified by name, then
+ * calls done_cb with the result and the data given as parameter. The result
+ * will be given to the done_cb as follows:
+ *
+ * canonname - the canonical name of the address, ip - the resolved ip address,
+ * addr - a pointer to the socket address, addrlen - the length of the socket
+ * address, in bytes, data - the data pointer given as parameter.
+ *
+ * @param[in] name IP address or server name to translate.
+ * @param[in] done_cb Callback to notify when done.
+ * @param[in] data User data to be given to done_cb.
+ *
+ * @return @c true if the request did not fail to be set up, @c false
+ * otherwise.
+ */
+EAPI Eina_Bool ecore_con_lookup(const char *name, Ecore_Con_Dns_Cb done_cb, const void *data) EINA_ARG_NONNULL(1);
+
+/**
* @}
*/
@@ -1142,6 +1221,10 @@ EAPI char *ecore_con_local_path_new(Eina_Bool is_system, const char *name, int p
* or changed with ecore_con_server_data_set().
*
* @see ecore_con_local_path_new()
+ *
+ * @note This API is deprecated and new code should use
+ * #EFL_NET_SERVER_SIMPLE_CLASS.
+ * See @li @ref efl_net_server_simple_example.c
*/
EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type,
const char *name, int port,
@@ -1194,6 +1277,10 @@ EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type,
* or changed with ecore_con_server_data_set().
*
* @see ecore_con_local_path_new()
+ *
+ * @note This API is deprecated and new code should use
+ * #EFL_NET_DIALER_SIMPLE_CLASS.
+ * See @li @ref efl_net_dialer_simple_example.c
*/
EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type,
const char *name, int port,
@@ -1211,6 +1298,18 @@ EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type,
EAPI void * ecore_con_server_del(Ecore_Con_Server *svr);
/**
+ * @brief Retrieves the name of server.
+ *
+ * The name returned is the name used to connect on this server.
+ *
+ * @param svr The given server.
+ * @return The name of the server.
+ *
+ * @ingroup Efl_Network_Server
+ */
+EAPI const char *ecore_con_server_name_get(const Ecore_Con_Server *svr);
+
+/**
* @brief Retrieve the data associated with the given server.
*
* @param svr The given server.
@@ -1304,6 +1403,21 @@ EAPI int ecore_con_server_send(Ecore_Con_Server *svr,
EAPI void ecore_con_server_client_limit_set(Ecore_Con_Server *svr,
int client_limit,
char reject_excess_clients);
+
+/**
+ * @brief Retrieves the current list of clients.
+ *
+ * Each node in the returned list points to an @ref Efl_Network_Client. This
+ * list cannot be modified or freed. It can also change if new clients are
+ * connected or disconnected, and will become invalid when the server is
+ * deleted/freed.
+ *
+ * @param svr The given server.
+ * @return The list of clients on this server.
+ *
+ */
+EAPI const Eina_List *ecore_con_server_clients_get(const Ecore_Con_Server *svr);
+
/**
* @brief Get the IP address of a server that has been connected to.
*
@@ -1532,7 +1646,13 @@ EAPI Eina_Bool ecore_con_client_connected_get(const Ecore_Con_Client *cl
*/
EAPI int ecore_con_client_port_get(const Ecore_Con_Client *cl);
-
+/**
+ * @brief The server the client is connected to.
+ *
+ * @param cl The client
+ * @return The server the client is connected to.
+ */
+EAPI Ecore_Con_Server *ecore_con_client_server_get(const Ecore_Con_Client *cl);
/**
* @}
diff --git a/src/lib/ecore_con/Ecore_Con_Eo.h b/src/lib/ecore_con/Ecore_Con_Eo.h
index e919d4ccb9..76c6d304ec 100644
--- a/src/lib/ecore_con/Ecore_Con_Eo.h
+++ b/src/lib/ecore_con/Ecore_Con_Eo.h
@@ -1,8 +1,3 @@
-#include "efl_network.eo.h"
-#include "efl_network_server.eo.h"
-#include "efl_network_connector.eo.h"
-#include "efl_network_client.eo.h"
-
#include "efl_net_socket.eo.h"
#include "efl_net_dialer.eo.h"
#include "efl_net_server.eo.h"
diff --git a/src/lib/ecore_con/Ecore_Con_Legacy.h b/src/lib/ecore_con/Ecore_Con_Legacy.h
deleted file mode 100644
index 1333eed935..0000000000
--- a/src/lib/ecore_con/Ecore_Con_Legacy.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _ECORE_CON_LEGACY_H
-#define _ECORE_CON_LEGACY_H
-#include <Eina.h>
-#include <Eo.h>
-
-#include "efl_network.eo.legacy.h"
-#include "efl_network_server.eo.legacy.h"
-#include "efl_network_connector.eo.legacy.h"
-#include "efl_network_client.eo.legacy.h"
-
-
-/********************************************************************
- * ecore_con_base.eo.h
- *******************************************************************/
-typedef Eo Ecore_Con_Base;
-
-
-/********************************************************************
- * ecore_con_client.eo.h
- *******************************************************************/
-typedef Eo Ecore_Con_Client;
-
-
-/********************************************************************
- * ecore_con_server.eo.h
- *******************************************************************/
-typedef Eo Ecore_Con_Server;
-
-#endif
diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
index e9dfd7621a..d603eae052 100644
--- a/src/lib/ecore_con/ecore_con.c
+++ b/src/lib/ecore_con/ecore_con.c
@@ -51,134 +51,11 @@
#define MSG_NOSIGNAL 0 /* noop */
#endif
-static Eina_Bool _ecore_con_client_timer(Ecore_Con_Client *cl);
-static void _ecore_con_cl_timer_update(Ecore_Con_Client *cl);
-static Eina_Bool _ecore_con_server_timer(Ecore_Con_Server *svr);
-static void _ecore_con_server_timer_update(Ecore_Con_Server *svr);
-
-static void _ecore_con_cb_tcp_connect(void *data,
- Ecore_Con_Info *info);
-static void _ecore_con_cb_udp_connect(void *data,
- Ecore_Con_Info *info);
-static void _ecore_con_cb_tcp_listen(void *data,
- Ecore_Con_Info *info);
-static void _ecore_con_cb_udp_listen(void *data,
- Ecore_Con_Info *info);
-
-static void _ecore_con_server_free(Ecore_Con_Server *svr);
-static void _ecore_con_client_free(Ecore_Con_Client *cl);
-
-static void _ecore_con_cl_read(Ecore_Con_Server *svr);
-static Eina_Bool _ecore_con_svr_tcp_handler(void *data,
- Ecore_Fd_Handler *fd_handler);
-static Eina_Bool _ecore_con_cl_handler(void *data,
- Ecore_Fd_Handler *fd_handler);
-static Eina_Bool _ecore_con_cl_udp_handler(void *data,
- Ecore_Fd_Handler *fd_handler);
-static Eina_Bool _ecore_con_svr_udp_handler(void *data,
- Ecore_Fd_Handler *fd_handler);
-
-static void _ecore_con_svr_cl_read(Ecore_Con_Client *cl);
-static Eina_Bool _ecore_con_svr_cl_handler(void *data,
- Ecore_Fd_Handler *fd_handler);
-
-static void _ecore_con_server_flush(Ecore_Con_Server *svr);
-static void _ecore_con_client_flush(Ecore_Con_Client *obj);
-
-static void _ecore_con_event_client_add_free(Ecore_Con_Server *svr,
- void *ev);
-static void _ecore_con_event_client_del_free(Ecore_Con_Server *svr,
- void *ev);
-static void _ecore_con_event_client_data_free(Ecore_Con_Server *svr,
- void *ev);
-static void _ecore_con_event_server_add_free(void *data,
- void *ev);
-static void _ecore_con_event_server_del_free(void *data,
- void *ev);
-static void _ecore_con_event_server_data_free(void *data,
- void *ev);
-static void _ecore_con_event_server_error_free(void *data,
- Ecore_Con_Event_Server_Error *e);
-static void _ecore_con_event_client_error_free(Ecore_Con_Server *svr,
- Ecore_Con_Event_Client_Error *e);
-static void _ecore_con_event_server_write_free(void *data,
- Ecore_Con_Event_Server_Write *e);
-static void _ecore_con_event_client_write_free(Ecore_Con_Server *svr,
- Ecore_Con_Event_Client_Write *e);
-
-static void _ecore_con_lookup_done(void *data,
- Ecore_Con_Info *infos);
-
-static const char *_ecore_con_pretty_ip(struct sockaddr *client_addr);
-
-#define EO_CONSTRUCTOR_CHECK_RETURN(obj) do { \
- if (efl_finalized_get(obj)) \
- { \
- ERR("This function is only allowed during construction."); \
- return; \
- } \
-} while (0)
-
#ifdef HAVE_SYSTEMD
int sd_fd_index = 0;
int sd_fd_max = 0;
#endif
-void
-_ecore_con_client_kill(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (cl->delete_me)
- DBG("Multi kill request for client %p", cl);
- else
- {
- ecore_con_event_client_del(obj);
- if (cl->buf) return;
- }
- INF("Lost client %s", (cl->ip) ? cl->ip : "");
- if (cl->fd_handler)
- ecore_main_fd_handler_del(cl->fd_handler);
-
- cl->fd_handler = NULL;
-}
-
-void
-_ecore_con_server_kill(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (svr->delete_me)
- DBG("Multi kill request for svr %p", svr);
- else
- ecore_con_event_server_del(obj);
-
- if (svr->fd_handler)
- ecore_main_fd_handler_del(svr->fd_handler);
-
- svr->fd_handler = NULL;
-}
-
-#define _ecore_con_server_kill(svr) do { \
- DBG("KILL %p", (svr)); \
- _ecore_con_server_kill((svr)); \
- } while (0)
-
-#define _ecore_con_client_kill(cl) do { \
- DBG("KILL %p", (cl)); \
- _ecore_con_client_kill((cl)); \
- } while (0)
-
-EAPI int ECORE_CON_EVENT_CLIENT_ADD = 0;
-EAPI int ECORE_CON_EVENT_CLIENT_DEL = 0;
-EAPI int ECORE_CON_EVENT_SERVER_ADD = 0;
-EAPI int ECORE_CON_EVENT_SERVER_DEL = 0;
-EAPI int ECORE_CON_EVENT_CLIENT_DATA = 0;
-EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
-EAPI int ECORE_CON_EVENT_CLIENT_WRITE = 0;
-EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
-EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
-EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
-EAPI int ECORE_CON_EVENT_PROXY_BIND = 0;
-
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_CONNECT = 0;
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY = 0;
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST = 0;
@@ -189,12 +66,8 @@ EWAPI Eina_Error EFL_NET_SERVER_ERROR_COULDNT_RESOLVE_HOST = 0;
EWAPI Eina_Error EFL_NET_SOCKET_SSL_ERROR_HANDSHAKE = 0;
EWAPI Eina_Error EFL_NET_SOCKET_SSL_ERROR_CERTIFICATE_VERIFY_FAILED = 0;
-static Eina_List *servers = NULL;
static int _ecore_con_init_count = 0;
-static int _ecore_con_event_count = 0;
int _ecore_con_log_dom = -1;
-Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
-Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
typedef struct pxProxyFactory_ pxProxyFactory;
typedef struct _Ecore_Con_Libproxy {
@@ -226,18 +99,7 @@ ecore_con_init(void)
goto ecore_con_log_error;
ecore_con_mempool_init();
-
- ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new();
- ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new();
- ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
- ECORE_CON_EVENT_CLIENT_WRITE = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
- ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
- ECORE_CON_EVENT_PROXY_BIND = ecore_event_type_new();
+ ecore_con_legacy_init();
EFL_NET_DIALER_ERROR_COULDNT_CONNECT = eina_error_msg_static_register("Couldn't connect to server");
EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY = eina_error_msg_static_register("Couldn't resolve proxy name");
@@ -249,16 +111,6 @@ ecore_con_init(void)
EFL_NET_SOCKET_SSL_ERROR_HANDSHAKE = eina_error_msg_static_register("Failed SSL handshake");
EFL_NET_SOCKET_SSL_ERROR_CERTIFICATE_VERIFY_FAILED = eina_error_msg_static_register("Failed to verify peer's certificate");
- eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
- eina_magic_string_set(ECORE_MAGIC_CON_CLIENT, "Ecore_Con_Client");
- eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
-
- /* TODO Remember return value, if it fails, use gethostbyname() */
- ecore_con_socks_init();
- ecore_con_ssl_init();
- ecore_con_info_init();
- ecore_con_local_init();
-
#ifdef HAVE_SYSTEMD
sd_fd_max = sd_listen_fds(0);
#endif
@@ -283,9 +135,6 @@ ecore_err:
EAPI int
ecore_con_shutdown(void)
{
- Eina_List *l, *l2;
- Ecore_Con_Server *obj;
-
/* _ecore_con_init_count should not go below zero. */
if (_ecore_con_init_count < 1)
{
@@ -310,26 +159,8 @@ ecore_con_shutdown(void)
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
- EINA_LIST_FOREACH_SAFE(servers, l, l2, obj)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Server_Add *ev;
-
- if (!svr) continue;
- svr->delete_me = EINA_TRUE;
- INF("svr %p is dead", svr);
- /* some pointer hacks here to prevent double frees if people are being stupid */
- EINA_LIST_FREE(svr->event_count, ev)
- ev->server = NULL;
- _ecore_con_server_free(obj);
- }
-
- ecore_con_socks_shutdown();
- if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
+ ecore_con_legacy_shutdown();
- ecore_con_local_shutdown();
- ecore_con_info_shutdown();
- ecore_con_ssl_shutdown();
eina_log_domain_unregister(_ecore_con_log_dom);
_ecore_con_log_dom = -1;
ecore_shutdown();
@@ -340,2695 +171,18 @@ ecore_con_shutdown(void)
return _ecore_con_init_count;
}
-EOLIAN static Eina_Bool
-_efl_network_lookup(Eo *kls_obj EINA_UNUSED, void *pd EINA_UNUSED, const char *name, Ecore_Con_Dns_Cb done_cb, const void *data)
-{
- Ecore_Con_Server *obj;
- Ecore_Con_Lookup *lk;
- struct addrinfo hints;
-
- if (!name || !done_cb)
- return EINA_FALSE;
-
- obj = efl_add(EFL_NETWORK_CONNECTOR_CLASS, NULL, efl_network_server_connection_type_set(efl_added, ECORE_CON_REMOTE_TCP), efl_network_server_name_set(efl_added, name), efl_network_port_set(efl_added, 1025));
-
- lk = malloc(sizeof (Ecore_Con_Lookup));
- if (!lk)
- {
- return EINA_FALSE;
- }
-
- lk->done_cb = done_cb;
- lk->data = data;
-
- ecore_con_server_data_set(obj, lk);
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_CANONNAME;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_canonname = NULL;
- hints.ai_next = NULL;
- hints.ai_addr = NULL;
-
- if (ecore_con_info_get(obj, _ecore_con_lookup_done, obj,
- &hints))
- return EINA_TRUE;
-
- free(lk);
- efl_del(obj);
- return EINA_FALSE;
-}
-
-/**
- * @addtogroup Ecore_Con_Server_Group Ecore Connection Server Functions
- *
- * Functions that operate on Ecore server objects.
- *
- * @{
- */
-
-/**
- * @example ecore_con_server_example.c
- * Shows how to write a simple server using the Ecore_Con library.
- */
-
-EAPI Ecore_Con_Server *
-ecore_con_server_add(Ecore_Con_Type compl_type,
- const char *name,
- int port,
- const void *data)
-{
- Ecore_Con_Server *obj;
-
- /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
- /* remote system socket: TCP/IP: [name]:[port] */
- obj = efl_add(EFL_NETWORK_SERVER_CLASS, NULL, efl_network_server_connection_type_set(efl_added, compl_type), efl_network_server_name_set(efl_added, name), efl_network_port_set(efl_added, port));
-
- ecore_con_server_data_set(obj, (void *) data);
-
- return obj;
-}
-
-EOLIAN static Eo *
-_efl_network_server_efl_object_constructor(Ecore_Con_Server *obj, Efl_Network_Server_Data *svr)
-{
- obj = efl_constructor(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
-
- svr->fd = INVALID_SOCKET;
- svr->reject_excess_clients = EINA_FALSE;
- svr->client_limit = -1;
- svr->clients = NULL;
-
- return obj;
-}
-
-EOLIAN static Eo *
-_efl_network_server_efl_object_finalize(Ecore_Con_Server *obj, Efl_Network_Server_Data *svr)
-{
- Ecore_Con_Type compl_type = svr->type;
- Ecore_Con_Type type;
-
- efl_finalize(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
-
- svr->created = EINA_TRUE;
- svr->ppid = getpid();
- svr->start_time = ecore_time_get();
- svr->use_cert = (svr->type & ECORE_CON_SSL & ECORE_CON_LOAD_CERT) == ECORE_CON_LOAD_CERT;
-
- servers = eina_list_append(servers, obj);
-
- if (!svr->name)
- goto error;
-
- type = compl_type & ECORE_CON_TYPE;
-
- EINA_SAFETY_ON_TRUE_GOTO(((type == ECORE_CON_REMOTE_TCP) ||
- (type == ECORE_CON_REMOTE_NODELAY) ||
- (type == ECORE_CON_REMOTE_CORK) ||
- (type == ECORE_CON_REMOTE_UDP) ||
- (type == ECORE_CON_REMOTE_BROADCAST)) &&
- (svr->port < 0), error);
-
- if (ecore_con_ssl_server_prepare(obj, compl_type & ECORE_CON_SSL))
- goto error;
-
- if ((type == ECORE_CON_LOCAL_USER) ||
- (type == ECORE_CON_LOCAL_SYSTEM) ||
- (type == ECORE_CON_LOCAL_ABSTRACT))
- /* Local */
-#ifdef _WIN32
- if (!ecore_con_local_listen(obj))
- goto error;
-#else
- if (!ecore_con_local_listen(obj, _ecore_con_svr_tcp_handler, obj))
- goto error;
-#endif
-
- if ((type == ECORE_CON_REMOTE_TCP) ||
- (type == ECORE_CON_REMOTE_NODELAY) ||
- (type == ECORE_CON_REMOTE_CORK))
- {
- /* TCP */
- if (!ecore_con_info_tcp_listen(obj, _ecore_con_cb_tcp_listen,
- obj))
- goto error;
- }
- else if ((type == ECORE_CON_REMOTE_MCAST) ||
- (type == ECORE_CON_REMOTE_UDP))
- /* UDP and MCAST */
- if (!ecore_con_info_udp_listen(obj, _ecore_con_cb_udp_listen,
- obj))
- goto error;
-
- return obj;
-
-error:
- if (svr->delete_me) return NULL;
- _ecore_con_server_kill(obj);
- return NULL;
-}
-
-EAPI Ecore_Con_Server *
-ecore_con_server_connect(Ecore_Con_Type compl_type,
- const char *name,
- int port,
- const void *data)
-{
- Ecore_Con_Server *obj;
- /* local user socket: FILE: ~/.ecore/[name]/[port] */
- /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
- /* remote system socket: TCP/IP: [name]:[port] */
- obj = efl_add(EFL_NETWORK_CONNECTOR_CLASS, NULL, efl_network_server_connection_type_set(efl_added, compl_type), efl_network_server_name_set(efl_added, name), efl_network_port_set(efl_added, port));
-
- ecore_con_server_data_set(obj, (void *) data);
-
- return obj;
-}
-
-EOLIAN static Eo *
-_efl_network_connector_efl_object_finalize(Ecore_Con_Server *obj, void *pd EINA_UNUSED)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Type compl_type = svr->type;
- Ecore_Con_Type type;
-
- /* XXX: We intentionally put SERVER class here and not connector, as we'd
- * like to skip that one. */
- efl_finalize(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
-
- svr->use_cert = (compl_type & ECORE_CON_SSL & ECORE_CON_LOAD_CERT) == ECORE_CON_LOAD_CERT;
- svr->disable_proxy = (compl_type & ECORE_CON_SUPER_SSL & ECORE_CON_NO_PROXY) == ECORE_CON_NO_PROXY;
- servers = eina_list_append(servers, obj);
-
- if (!svr->name || !(svr->name[0]))
- goto error;
-
- type = compl_type & ECORE_CON_TYPE;
-
- if ((!svr->disable_proxy) && (type > ECORE_CON_LOCAL_ABSTRACT))
- {
- /* never use proxies on local connections */
- if (_ecore_con_proxy_once)
- svr->ecs = _ecore_con_proxy_once;
- else if (_ecore_con_proxy_global)
- svr->ecs = _ecore_con_proxy_global;
- _ecore_con_proxy_once = NULL;
- if (svr->ecs)
- {
- if ((!svr->ecs->lookup) &&
- (!ecore_con_lookup(svr->name, (Ecore_Con_Dns_Cb)ecore_con_socks_dns_cb, svr)))
- goto error;
- if (svr->ecs->lookup)
- svr->ecs_state = ECORE_CON_PROXY_STATE_RESOLVED;
- }
- }
- EINA_SAFETY_ON_TRUE_GOTO(ecore_con_ssl_server_prepare(obj, compl_type & ECORE_CON_SSL), error);
-
- EINA_SAFETY_ON_TRUE_GOTO(((type == ECORE_CON_REMOTE_TCP) ||
- (type == ECORE_CON_REMOTE_NODELAY) ||
- (type == ECORE_CON_REMOTE_CORK) ||
- (type == ECORE_CON_REMOTE_UDP) ||
- (type == ECORE_CON_REMOTE_BROADCAST)) &&
- (svr->port < 0), error);
-
- if ((type == ECORE_CON_LOCAL_USER) ||
- (type == ECORE_CON_LOCAL_SYSTEM) ||
- (type == ECORE_CON_LOCAL_ABSTRACT))
- /* Local */
-#ifdef _WIN32
- if (!ecore_con_local_connect(obj, _ecore_con_cl_handler)) goto error;
-#else
- if (!ecore_con_local_connect(obj, _ecore_con_cl_handler, obj)) goto error;
-#endif
-
- if ((type == ECORE_CON_REMOTE_TCP) ||
- (type == ECORE_CON_REMOTE_NODELAY) ||
- (type == ECORE_CON_REMOTE_CORK))
- {
- /* TCP */
- EINA_SAFETY_ON_FALSE_GOTO(ecore_con_info_tcp_connect(obj, _ecore_con_cb_tcp_connect, obj), error);
- }
- else if ((type == ECORE_CON_REMOTE_UDP) || (type == ECORE_CON_REMOTE_BROADCAST))
- /* UDP and MCAST */
- EINA_SAFETY_ON_FALSE_GOTO(ecore_con_info_udp_connect(obj, _ecore_con_cb_udp_connect, obj), error);
-
- return obj;
-
-error:
- return NULL;
-}
-
-EAPI void
-ecore_con_server_timeout_set(Ecore_Con *obj, double timeout)
-{
- efl_network_timeout_set((Ecore_Con *)obj, timeout);
-}
-
-EOLIAN static void
-_efl_network_server_efl_network_timeout_set(Eo *obj, Efl_Network_Server_Data *svr, double timeout)
-{
- if (svr->created)
- svr->client_disconnect_time = timeout;
- else
- svr->disconnect_time = timeout;
-
- _ecore_con_server_timer_update(obj);
-}
-
-EAPI double
-ecore_con_server_timeout_get(const Ecore_Con *obj)
-{
- return efl_network_timeout_get((Ecore_Con *)obj);
-}
-
-EOLIAN static double
-_efl_network_server_efl_network_timeout_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->created ? svr->client_disconnect_time : svr->disconnect_time;
-}
-
-EAPI void *
-ecore_con_server_del(Ecore_Con_Server *obj)
-{
- if (!obj) return NULL;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
-
- if (!svr || svr->delete_me)
- return NULL;
-
-#ifdef _WIN32
- WSASendDisconnect(svr->fd, NULL);
-#endif
- _ecore_con_server_kill(obj);
- return svr->data;
-}
-
-EAPI void *
-ecore_con_server_data_get(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr)
- return NULL;
-
- return svr->data;
-}
-
-EAPI void *
-ecore_con_server_data_set(Ecore_Con_Server *obj,
- void *data)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- void *ret = NULL;
-
- if (!svr)
- return NULL;
-
- ret = svr->data;
- svr->data = data;
- return ret;
-}
-
-EAPI Eina_Bool
-ecore_con_server_connected_get(const Ecore_Con *obj)
-{
- return efl_network_connected_get((Ecore_Con *)obj);
-}
-
-EOLIAN static Eina_Bool
-_efl_network_server_efl_network_connected_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return !svr->connecting;
-}
-
-EOLIAN static const Eina_List *
-_efl_network_server_clients_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->clients;
-}
-
-EOLIAN static void
-_efl_network_server_connection_type_set(Eo *obj, Efl_Network_Server_Data *svr, Ecore_Con_Type type)
-{
- EO_CONSTRUCTOR_CHECK_RETURN(obj);
-
- svr->type = type;
-}
-
-EOLIAN static Ecore_Con_Type
-_efl_network_server_connection_type_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->type;
-}
-
-EOLIAN static void
-_efl_network_server_name_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, const char *name)
-{
- EO_CONSTRUCTOR_CHECK_RETURN(obj);
-
- if (svr->name)
- free(svr->name);
-
- svr->name = strdup(name);
-}
-
-EOLIAN static const char *
-_efl_network_server_name_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->name;
-}
-
-EAPI int
-ecore_con_server_port_get(const Ecore_Con *obj)
-{
- return efl_network_port_get((Ecore_Con *)obj);
-}
-
-EOLIAN static void
-_efl_network_server_efl_network_port_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, int port)
-{
- EO_CONSTRUCTOR_CHECK_RETURN(obj);
-
- svr->port = port;
-}
-
-EOLIAN static int
-_efl_network_server_efl_network_port_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->port;
-}
-
-EAPI int
-ecore_con_server_send(Ecore_Con *obj, const void *data, int size)
-{
- return efl_network_send((Ecore_Con *)obj, data, size);
-}
-
-EOLIAN static int
-_efl_network_server_efl_network_send(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, const void *data, int size)
-{
- EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->delete_me, 0);
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
-
- EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
-
- if (svr->fd_handler)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
-
- if (!svr->buf)
- {
- svr->buf = eina_binbuf_new();
- EINA_SAFETY_ON_NULL_RETURN_VAL(svr->buf, 0);
-#ifdef TCP_CORK
- if ((svr->fd != INVALID_SOCKET) && ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK))
- {
- int state = 1;
- if (setsockopt(svr->fd, IPPROTO_TCP, TCP_CORK, (char *)&state, sizeof(int)) < 0)
- /* realistically this isn't anything serious so we can just log and continue */
- ERR("corking failed! %s", strerror(errno));
- }
-#endif
- }
- if (!eina_binbuf_append_length(svr->buf, data, size))
- ERR("eina_binbuf_append_length() failed");
-
- return size;
-}
-
-EOLIAN static void
-_efl_network_server_client_limit_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr,
- int client_limit,
- char reject_excess_clients)
-{
- svr->client_limit = client_limit;
- svr->reject_excess_clients = reject_excess_clients;
-}
-
-EOLIAN static void
-_efl_network_server_client_limit_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr,
- int *client_limit,
- char *reject_excess_clients)
-{
- if (client_limit) *client_limit = svr->client_limit;
- if (reject_excess_clients) *reject_excess_clients = svr->reject_excess_clients;
-}
-
-EAPI const char *
-ecore_con_server_ip_get(const Ecore_Con *obj)
-{
- return efl_network_ip_get(obj);
-}
-
-EOLIAN static const char *
-_efl_network_server_efl_network_ip_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return svr->ip;
-}
-
-EAPI double
-ecore_con_server_uptime_get(const Ecore_Con *obj)
-{
- return efl_network_uptime_get(obj);
-}
-
-EOLIAN static double
-_efl_network_server_efl_network_uptime_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- return ecore_time_get() - svr->start_time;
-}
-
-EAPI void
-ecore_con_server_flush(Ecore_Con *obj)
-{
- efl_network_flush((Ecore_Con *)obj);
-}
-
-EOLIAN static void
-_efl_network_server_efl_network_flush(Eo *obj, Efl_Network_Server_Data *svr EINA_UNUSED)
-{
- _ecore_con_server_flush(obj);
-}
-
-/**
- * @}
- */
-
-/**
- * @addtogroup Ecore_Con_Client_Group Ecore Connection Client Functions
- *
- * Functions that operate on Ecore connection client objects.
- *
- * @{
- */
-
-/**
- * @example ecore_con_client_example.c
- * Shows how to write a simple client that connects to the example server.
- */
-
-EAPI int
-ecore_con_client_send(Ecore_Con *obj, const void *data, int size)
-{
- return efl_network_send((Ecore_Con *)obj, data, size);
-}
-
-EOLIAN static int
-_efl_network_client_efl_network_send(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl, const void *data, int size)
-{
- Efl_Network_Server_Data *host_server = NULL;
- EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->delete_me, 0);
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
-
- EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
-
- if (cl->fd_handler)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
-
- if (cl->host_server)
- host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_CLIENT_CLASS);
-
-
- if (cl->host_server && ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP))
- {
- int ret;
-
- ret = (int)sendto(host_server->fd, data, size, 0,
- (struct sockaddr *)cl->client_addr,
- cl->client_addr_len);
- return ret;
- }
- else
- {
- if (!cl->buf)
- {
- cl->buf = eina_binbuf_new();
- EINA_SAFETY_ON_NULL_RETURN_VAL(cl->buf, 0);
-#ifdef TCP_CORK
- if ((cl->fd != INVALID_SOCKET) && (host_server) &&
- ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK))
- {
- int state = 1;
- if (setsockopt(cl->fd, IPPROTO_TCP, TCP_CORK, (char *)&state, sizeof(int)) < 0)
- /* realistically this isn't anything serious so we can just log and continue */
- ERR("corking failed! %s", strerror(errno));
- }
-#endif
- }
- if (!eina_binbuf_append_length(cl->buf, data, size))
- ERR("eina_binbuf_append_length() failed");
- }
- return size;
-}
-
-EOLIAN static Ecore_Con_Server *
-_efl_network_client_server_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- return cl->host_server;
-}
-
-EOLIAN static Eina_Bool
-_efl_network_client_efl_network_connected_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- return !cl->delete_me;
-}
-
-EAPI Eina_Bool
-ecore_con_client_connected_get(const Ecore_Con *obj)
-{
- return efl_network_connected_get((Ecore_Con *)obj);
-}
-
-EOLIAN static void
-_efl_network_client_efl_network_timeout_set(Eo *obj, Efl_Network_Client_Data *cl, double timeout)
-{
- cl->disconnect_time = timeout;
-
- _ecore_con_cl_timer_update(obj);
-}
-
-EAPI void
-ecore_con_client_timeout_set(Ecore_Con *obj, double timeout)
-{
- efl_network_timeout_set((Ecore_Con *)obj, timeout);
-}
-
-EOLIAN static double
-_efl_network_client_efl_network_timeout_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- return cl->disconnect_time;
-}
-
-EAPI double
-ecore_con_client_timeout_get(const Ecore_Con *obj)
-{
- return efl_network_timeout_get((Ecore_Con *)obj);
-}
-
-EAPI void *
-ecore_con_client_del(Ecore_Con_Client *obj)
-{
- if (!obj) return NULL;
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl) return NULL;
-
-#ifdef _WIN32
- WSASendDisconnect(cl->fd, NULL);
-#endif
-
- _ecore_con_client_kill(obj);
- return cl->data;
-}
-
-EAPI void
-ecore_con_client_data_set(Ecore_Con_Client *obj,
- const void *data)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- return;
-
- cl->data = (void *)data;
-}
-
-EAPI void *
-ecore_con_client_data_get(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- return NULL;
-
- return cl->data;
-}
-
-EOLIAN static const char *
-_efl_network_client_efl_network_ip_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- if (!cl->ip)
- cl->ip = _ecore_con_pretty_ip(cl->client_addr);
-
- return cl->ip;
-}
-
-EAPI const char *
-ecore_con_client_ip_get(const Ecore_Con *obj)
-{
- return efl_network_ip_get(obj);
-}
-
-EOLIAN static int
-_efl_network_client_efl_network_port_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- Efl_Network_Server_Data *sd = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- if (sd->type != ECORE_CON_REMOTE_TCP &&
- sd->type != ECORE_CON_REMOTE_MCAST &&
- sd->type != ECORE_CON_REMOTE_UDP &&
- sd->type != ECORE_CON_REMOTE_BROADCAST &&
- sd->type != ECORE_CON_REMOTE_NODELAY)
- return -1;
-
- if (cl->client_addr->sa_family == AF_INET)
- return ((struct sockaddr_in *)cl->client_addr)->sin_port;
-#ifdef HAVE_IPV6
- return ((struct sockaddr_in6 *)cl->client_addr)->sin6_port;
-#else
- return -1;
-#endif
-}
-
-EAPI int
-ecore_con_client_port_get(const Ecore_Con *obj)
-{
- return efl_network_port_get((Ecore_Con *)obj);
-}
-
-EOLIAN static double
-_efl_network_client_efl_network_uptime_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- return ecore_time_get() - cl->start_time;
-}
-
-EAPI double
-ecore_con_client_uptime_get(const Ecore_Con *obj)
-{
- return efl_network_uptime_get(obj);
-}
-
-EOLIAN static void
-_efl_network_client_efl_network_flush(Eo *obj, Efl_Network_Client_Data *cl EINA_UNUSED)
-{
- _ecore_con_client_flush(obj);
-}
-
-EAPI void
-ecore_con_client_flush(Ecore_Con *obj)
-{
- efl_network_flush((Ecore_Con *)obj);
-}
-
EAPI int
-ecore_con_server_fd_get(const Ecore_Con *obj)
-{
- return efl_network_fd_get((Ecore_Con *)obj);
-}
-
-EOLIAN static int
-_efl_network_server_efl_network_fd_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
-{
- if (svr->created) return -1;
- if (svr->delete_me) return -1;
- return ecore_main_fd_handler_fd_get(svr->fd_handler);
-}
-
-EOLIAN static int
-_efl_network_client_efl_network_fd_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
-{
- return ecore_main_fd_handler_fd_get(cl->fd_handler);
-}
-
-EAPI int
-ecore_con_client_fd_get(const Ecore_Con *obj)
-{
- return efl_network_fd_get((Ecore_Con *)obj);
-}
-
-/**
- * @}
- */
-
-void
-ecore_con_event_proxy_bind(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Proxy_Bind *e;
- int ev = ECORE_CON_EVENT_PROXY_BIND;
-
- e = ecore_con_event_proxy_bind_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- svr->event_count = eina_list_append(svr->event_count, e);
- _ecore_con_server_timer_update(obj);
- e->server = obj;
- e->ip = svr->proxyip;
- e->port = svr->proxyport;
- ecore_event_add(ev, e,
- _ecore_con_event_server_add_free, NULL);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_server_add(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- /* we got our server! */
- Ecore_Con_Event_Server_Add *e;
- int ev = ECORE_CON_EVENT_SERVER_ADD;
-
- e = ecore_con_event_server_add_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- svr->connecting = EINA_FALSE;
- svr->start_time = ecore_time_get();
- svr->event_count = eina_list_append(svr->event_count, e);
- _ecore_con_server_timer_update(obj);
- e->server = obj;
- if (svr->upgrade) ev = ECORE_CON_EVENT_SERVER_UPGRADE;
- ecore_event_add(ev, e,
- _ecore_con_event_server_add_free, NULL);
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_UPGRADED, NULL);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_server_del(Ecore_Con_Server *obj)
+ecore_con_ssl_available_get(void)
{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Server_Del *e;
-
- svr->delete_me = EINA_TRUE;
- INF("svr %p is dead", svr);
- e = ecore_con_event_server_del_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- svr->event_count = eina_list_append(svr->event_count, e);
- _ecore_con_server_timer_update(obj);
- e->server = obj;
- if (svr->ecs)
- {
- svr->ecs_state = svr->ecs->lookup ? ECORE_CON_PROXY_STATE_RESOLVED : ECORE_CON_PROXY_STATE_DONE;
- eina_stringshare_replace(&svr->proxyip, NULL);
- svr->proxyport = 0;
- }
- ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, e,
- _ecore_con_event_server_del_free, NULL);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_server_write(Ecore_Con_Server *obj, int num)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Server_Write *e;
-
- e = ecore_con_event_server_write_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- INF("Wrote %d bytes", num);
- svr->event_count = eina_list_append(svr->event_count, e);
- e->server = obj;
- e->size = num;
- ecore_event_add(ECORE_CON_EVENT_SERVER_WRITE, e,
- (Ecore_End_Cb)_ecore_con_event_server_write_free, NULL);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_server_data(Ecore_Con_Server *obj, unsigned char *buf, int num, Eina_Bool duplicate)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Server_Data *e;
-
- e = ecore_con_event_server_data_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- svr->event_count = eina_list_append(svr->event_count, e);
- _ecore_con_server_timer_update(obj);
- e->server = obj;
- if (duplicate)
- {
- e->data = malloc(num);
- if (!e->data)
- {
- ERR("server data allocation failure !");
- _ecore_con_event_server_data_free(NULL, e);
- return;
- }
- memcpy(e->data, buf, num);
- }
- else
- e->data = buf;
- e->size = num;
- ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
- _ecore_con_event_server_data_free, NULL);
- {
- Ecore_Con_Event_Data_Received event_info = { NULL, 0 };
- event_info.data = e->data;
- event_info.size = e->size;
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_DATA_RECEIVED, &event_info);
- }
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_client_add(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Client_Add *e;
- int ev = ECORE_CON_EVENT_CLIENT_ADD;
-
- e = ecore_con_event_client_add_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- cl->event_count = eina_list_append(cl->event_count, e);
- host_server->event_count = eina_list_append(host_server->event_count, e);
- _ecore_con_cl_timer_update(obj);
- cl->start_time = ecore_time_get();
- e->client = obj;
- if (cl->upgrade) ev = ECORE_CON_EVENT_CLIENT_UPGRADE;
- ecore_event_add(ev, e,
- (Ecore_End_Cb)_ecore_con_event_client_add_free, cl->host_server);
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_UPGRADED, NULL);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_client_del(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Client_Del *e;
-
- if (!cl) return;
- cl->delete_me = EINA_TRUE;
- INF("cl %p is dead", cl);
- e = ecore_con_event_client_del_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
- cl->event_count = eina_list_append(cl->event_count, e);
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- host_server->event_count = eina_list_append(host_server->event_count, e);
- _ecore_con_cl_timer_update(obj);
- e->client = obj;
- ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
- (Ecore_End_Cb)_ecore_con_event_client_del_free, cl->host_server);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_client_write(Ecore_Con_Client *obj, int num)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Client_Write *e;
-
- e = ecore_con_event_client_write_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- cl->event_count = eina_list_append(cl->event_count, e);
- host_server->event_count = eina_list_append(host_server->event_count, e);
- e->client = obj;
- e->size = num;
- ecore_event_add(ECORE_CON_EVENT_CLIENT_WRITE, e,
- (Ecore_End_Cb)_ecore_con_event_client_write_free, cl->host_server);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_client_data(Ecore_Con_Client *obj, unsigned char *buf, int num, Eina_Bool duplicate)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Client_Data *e;
-
- e = ecore_con_event_client_data_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- cl->event_count = eina_list_append(cl->event_count, e);
- host_server->event_count = eina_list_append(host_server->event_count, e);
- _ecore_con_cl_timer_update(obj);
- e->client = obj;
- if ((duplicate) && (num > 0))
- {
- e->data = malloc(num);
- if (!e->data)
- {
- ERR("client data allocation failure !");
- _ecore_con_event_client_data_free(cl->host_server, e);
- return;
- }
- memcpy(e->data, buf, num);
- }
- else
- e->data = buf;
- e->size = num;
- ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
- (Ecore_End_Cb)_ecore_con_event_client_data_free, cl->host_server);
- {
- Ecore_Con_Event_Data_Received event_info = { NULL, 0 };
- event_info.data = e->data;
- event_info.size = e->size;
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_DATA_RECEIVED, &event_info);
- }
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_server_infos_del(Ecore_Con_Server *obj, void *info)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- svr->infos = eina_list_remove(svr->infos, info);
-}
-
-void
-_ecore_con_event_server_error(Ecore_Con_Server *obj, char *error, Eina_Bool duplicate)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Server_Error *e;
-
- e = ecore_con_event_server_error_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- e->server = obj;
- e->error = duplicate ? strdup(error) : error;
- DBG("%s", error);
- svr->event_count = eina_list_append(svr->event_count, e);
- ecore_event_add(ECORE_CON_EVENT_SERVER_ERROR, e, (Ecore_End_Cb)_ecore_con_event_server_error_free, NULL);
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_ERROR, e->error);
- _ecore_con_event_count++;
-}
-
-void
-ecore_con_event_client_error(Ecore_Con_Client *obj, const char *error)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Client_Error *e;
-
- e = ecore_con_event_client_error_alloc();
- EINA_SAFETY_ON_NULL_RETURN(e);
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- e->client = obj;
- e->error = strdup(error);
- DBG("%s", error);
- cl->event_count = eina_list_append(cl->event_count, e);
- host_server->event_count = eina_list_append(host_server->event_count, e);
- ecore_event_add(ECORE_CON_EVENT_CLIENT_ERROR, e, (Ecore_End_Cb)_ecore_con_event_client_error_free, cl->host_server);
- efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_ERROR, e->error);
- _ecore_con_event_count++;
-}
-
-static void
-_ecore_con_server_free(Ecore_Con_Server *obj)
-{
- efl_del(obj);
-}
-
-EOLIAN static void
-_efl_network_server_efl_object_destructor(Eo *obj, Efl_Network_Server_Data *svr)
-{
- Ecore_Con_Client *cl_obj;
- double t_start, t;
-
- if (svr->event_count) goto end;
-
- while (svr->infos)
- {
- ecore_con_info_data_clear(svr->infos->data);
- svr->infos = eina_list_remove_list(svr->infos, svr->infos);
- }
-
- t_start = ecore_time_get();
- while (svr->buf && (!svr->delete_me))
- {
- _ecore_con_server_flush(obj);
- t = ecore_time_get();
- if ((t - t_start) > 0.5)
- {
- WRN("ECORE_CON: EEK - stuck in _ecore_con_server_free() trying\n"
- " to flush data out from the server, and have been for\n"
- " %1.1f seconds. This is taking too long. Aborting flush.",
- (t - t_start));
- break;
- }
- }
-
-#ifdef _WIN32
- ecore_con_local_win32_server_del(obj);
-#endif
- if (svr->event_count) goto end;
-
- if (svr->buf)
- eina_binbuf_free(svr->buf);
-
- EINA_LIST_FREE(svr->clients, cl_obj)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(cl_obj, EFL_NETWORK_CLIENT_CLASS);
- Ecore_Con_Event_Server_Add *ev;
-
- /* some pointer hacks here to prevent double frees if people are being stupid */
- EINA_LIST_FREE(cl->event_count, ev)
- ev->server = NULL;
- cl->delete_me = EINA_TRUE;
- INF("cl %p is dead", cl);
- _ecore_con_client_free(cl_obj);
- }
- if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
- unlink(svr->path);
-
- ecore_con_ssl_server_shutdown(obj);
- free(svr->name);
- svr->name = NULL;
-
- free(svr->path);
- svr->path = NULL;
-
- eina_stringshare_del(svr->ip);
- eina_stringshare_del(svr->verify_name);
-
- if (svr->ecs_buf) eina_binbuf_free(svr->ecs_buf);
- if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
-
- if (svr->fd_handler)
- ecore_main_fd_handler_del(svr->fd_handler);
-
- if (svr->fd != INVALID_SOCKET)
- closesocket(svr->fd);
-
- if (svr->until_deletion)
- ecore_timer_del(svr->until_deletion);
-
- servers = eina_list_remove(servers, obj);
- svr->data = NULL;
-
- efl_destructor(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
-end:
- return;
-}
-
-static void
-_ecore_con_client_free(Ecore_Con_Client *obj)
-{
- efl_del(obj);
-}
-
-EOLIAN static void
-_efl_network_client_efl_object_destructor(Eo *obj, Efl_Network_Client_Data *cl)
-{
- double t_start, t;
-
- if (cl->event_count) return;
-
- t_start = ecore_time_get();
- while ((cl->buf) && (!cl->delete_me))
- {
- _ecore_con_client_flush(obj);
- t = ecore_time_get();
- if ((t - t_start) > 0.5)
- {
- WRN("EEK - stuck in _ecore_con_client_free() trying\n"
- " to flush data out from the client, and have been for\n"
- " %1.1f seconds. This is taking too long. Aborting flush.",
- (t - t_start));
- break;
- }
- }
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- if (host_server)
- {
- host_server->clients = eina_list_remove(host_server->clients, obj);
- --host_server->client_count;
- }
-
-#ifdef _WIN32
- ecore_con_local_win32_client_del(obj);
-#endif
-
- if (cl->event_count) return;
-
- if (cl->buf) eina_binbuf_free(cl->buf);
-
- if (host_server && (host_server->type & ECORE_CON_SSL))
- ecore_con_ssl_client_shutdown(obj);
-
- if (cl->fd_handler)
- ecore_main_fd_handler_del(cl->fd_handler);
-
- if (cl->fd != INVALID_SOCKET)
- closesocket(cl->fd);
-
- free(cl->client_addr);
- cl->client_addr = NULL;
-
- if (cl->until_deletion)
- ecore_timer_del(cl->until_deletion);
-
- eina_stringshare_del(cl->ip);
- cl->data = NULL;
-
- efl_destructor(efl_super(obj, EFL_NETWORK_CLIENT_CLASS));
-}
-
-static Eina_Bool
-_ecore_con_server_timer(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- ecore_con_server_del(obj);
-
- svr->until_deletion = NULL;
- return ECORE_CALLBACK_CANCEL;
-}
-
-static void
-_ecore_con_server_timer_update(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (svr->disconnect_time)
- {
- if (svr->disconnect_time > 0)
- {
- if (svr->until_deletion)
- {
- ecore_timer_interval_set(svr->until_deletion, svr->disconnect_time);
- ecore_timer_reset(svr->until_deletion);
- }
- else
- svr->until_deletion = ecore_timer_add(svr->disconnect_time, (Ecore_Task_Cb)_ecore_con_server_timer, obj);
- }
- else if (svr->until_deletion)
- {
- ecore_timer_del(svr->until_deletion);
- svr->until_deletion = NULL;
- }
- }
- else
- {
- if (svr->until_deletion)
- {
- ecore_timer_del(svr->until_deletion);
- svr->until_deletion = NULL;
- }
- }
-}
-
-static Eina_Bool
-_ecore_con_client_timer(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- ecore_con_client_del(obj);
-
- cl->until_deletion = NULL;
- return ECORE_CALLBACK_CANCEL;
-}
-
-static void
-_ecore_con_cl_timer_update(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (cl->disconnect_time)
- {
- if (cl->disconnect_time > 0)
- {
- if (cl->until_deletion)
- {
- ecore_timer_interval_set(cl->until_deletion, cl->disconnect_time);
- ecore_timer_reset(cl->until_deletion);
- }
- else
- cl->until_deletion = ecore_timer_add(cl->disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, obj);
- }
- else if (cl->until_deletion)
- {
- ecore_timer_del(cl->until_deletion);
- cl->until_deletion = NULL;
- }
- }
- else
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
-
- if (host_server && host_server->client_disconnect_time > 0)
- {
- if (cl->until_deletion)
- {
- ecore_timer_interval_set(cl->until_deletion, host_server->client_disconnect_time);
- ecore_timer_reset(cl->until_deletion);
- }
- else
- cl->until_deletion = ecore_timer_add(host_server->client_disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, obj);
- }
- else if (cl->until_deletion)
- {
- ecore_timer_del(cl->until_deletion);
- cl->until_deletion = NULL;
- }
- }
-}
-
-static void
-_ecore_con_cb_tcp_listen(void *data,
- Ecore_Con_Info *net_info)
-{
- Ecore_Con_Server *obj = data;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- struct linger lin;
- const char *memerr = NULL;
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- errno = 0;
- if (!net_info) /* error message has already been handled */
- {
- svr->delete_me = EINA_TRUE;
- goto error;
- }
-
-#ifdef HAVE_SYSTEMD
- if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
- {
- if (sd_is_socket_inet(SD_LISTEN_FDS_START + sd_fd_index,
- net_info->info.ai_family,
- net_info->info.ai_socktype,
- 1,
- svr->port) <= 0)
- {
- ERR("Your systemd unit seems to provide fd in the wrong order for Socket activation.");
- goto error;
- }
-
- svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
-
- /* I am wondering if that's really going to work as the bind is already done */
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
-
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
- sizeof(struct linger)) < 0)
- goto error;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
- {
- int flag = 1;
-
- if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
- sizeof(int)) < 0)
- {
- goto error;
- }
- }
-
- goto fd_ready;
- }
-#endif
-
- svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
- net_info->info.ai_protocol);
-#ifdef _WIN32
- if (svr->fd == INVALID_SOCKET) goto error;
-
- if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
+#if HAVE_GNUTLS
+ return 1;
+#elif HAVE_OPENSSL
+ return 2;
#else
- if (svr->fd < 0) goto error;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+ return 0;
#endif
-
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
- sizeof(struct linger)) < 0)
- goto error;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
- {
- int flag = 1;
-
- if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
- sizeof(int)) < 0)
- {
- goto error;
- }
- }
-
- if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) != 0)
- goto error;
-
- if (listen(svr->fd, 4096) != 0) goto error;
-
-#ifdef HAVE_SYSTEMD
-fd_ready:
-#endif
- svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_svr_tcp_handler, obj, NULL, NULL);
- if (!svr->fd_handler)
- {
- memerr = "Memory allocation failure";
- goto error;
- }
-
- return;
-
-error:
- if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
- ecore_con_ssl_server_shutdown(obj);
- _ecore_con_server_kill(obj);
-}
-
-static void
-_ecore_con_cb_udp_listen(void *data,
- Ecore_Con_Info *net_info)
-{
- Ecore_Con_Server *obj = data;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Type type;
- struct ip_mreq mreq;
-#ifdef HAVE_IPV6
- struct ipv6_mreq mreq6;
-#endif
- const int on = 1;
- const char *memerr = NULL;
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- type = svr->type;
- type &= ECORE_CON_TYPE;
-
- errno = 0;
- if (!net_info) /* error message has already been handled */
- {
- svr->delete_me = EINA_TRUE;
- goto error;
- }
-#ifdef HAVE_SYSTEMD
- if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
- {
- if (sd_is_socket_inet(SD_LISTEN_FDS_START + sd_fd_index,
- net_info->info.ai_family,
- net_info->info.ai_socktype,
- -1,
- svr->port) <= 0)
- {
- ERR("Your systemd unit seems to provide fd in the wrong order for Socket activation.");
- goto error;
- }
- svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
-
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0)
- goto error;
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
-
- goto fd_ready;
- }
-#endif
- svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
- net_info->info.ai_protocol);
-#ifdef _WIN32
- if (svr->fd == INVALID_SOCKET) goto error;
-
- if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
-#else
- if (svr->fd < 0) goto error;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
-#endif
-
- if (type == ECORE_CON_REMOTE_MCAST)
- {
- if (net_info->info.ai_family == AF_INET)
- {
- if (!inet_pton(net_info->info.ai_family, net_info->ip,
- &mreq.imr_multiaddr))
- goto error;
-
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (const void *)&mreq, sizeof(mreq)) != 0)
- goto error;
- }
-#ifdef HAVE_IPV6
- else if (net_info->info.ai_family == AF_INET6)
- {
- if (!inet_pton(net_info->info.ai_family, net_info->ip,
- &mreq6.ipv6mr_multiaddr))
- goto error;
- mreq6.ipv6mr_interface = htonl(INADDR_ANY);
- if (setsockopt(svr->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (const void *)&mreq6, sizeof(mreq6)) != 0)
- goto error;
- }
-#endif
- }
-
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0)
- goto error;
-
- if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
- goto error;
-
-#ifdef HAVE_SYSTEMD
-fd_ready:
-#endif
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_svr_udp_handler, obj, NULL, NULL);
- if (!svr->fd_handler)
- {
- memerr = "Memory allocation failure";
- goto error;
- }
-
- svr->ip = eina_stringshare_add(net_info->ip);
-
- return;
-
-error:
- if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
- ecore_con_ssl_server_shutdown(obj);
- _ecore_con_server_kill(obj);
-}
-
-static void
-_ecore_con_cb_tcp_connect(void *data,
- Ecore_Con_Info *net_info)
-{
- Ecore_Con_Server *obj = data;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int res;
- int curstate = 0;
- const char *memerr = NULL;
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- errno = 0;
- if (!net_info) /* error message has already been handled */
- {
- svr->delete_me = EINA_TRUE;
- goto error;
- }
-
- svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
- net_info->info.ai_protocol);
-#ifdef _WIN32
- if (svr->fd == INVALID_SOCKET) goto error;
-
- if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
-#else
- if (svr->fd < 0) goto error;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
-#endif
-
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0)
- goto error;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
- {
- int flag = 1;
-
- if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0)
- {
- goto error;
- }
- }
-
- res = connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen);
-#ifdef _WIN32
- if (res == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- char *err;
- err = evil_format_message(WSAGetLastError());
- _ecore_con_event_server_error(obj, err, EINA_FALSE);
- ecore_con_ssl_server_shutdown(obj);
- _ecore_con_server_kill(obj);
- return;
- }
-
-#else
- if (res < 0)
- {
- if (errno != EINPROGRESS) goto error;
-#endif
- svr->connecting = EINA_TRUE;
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
- _ecore_con_cl_handler, obj, NULL, NULL);
- }
- else
- {
- ecore_con_event_server_add(obj);
- svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_cl_handler, obj, NULL, NULL);
- }
-
- if (svr->type & ECORE_CON_SSL)
- {
- svr->handshaking = EINA_TRUE;
- svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
- DBG("%s ssl handshake", svr->ecs_state ? "Queuing" : "Beginning");
- if ((!svr->ecs_state) && ecore_con_ssl_server_init(obj))
- goto error;
- }
-
- if (!svr->fd_handler)
- {
- memerr = "Memory allocation failure";
- goto error;
- }
-
- if ((!svr->ecs) || (svr->ecs->lookup))
- svr->ip = eina_stringshare_add(net_info->ip);
-
- return;
-
-error:
- ecore_con_event_server_error(obj,
- memerr ? : errno ? strerror(errno) : "DNS error");
- ecore_con_ssl_server_shutdown(obj);
- _ecore_con_server_kill(obj);
-}
-
-static void
-_ecore_con_cb_udp_connect(void *data,
- Ecore_Con_Info *net_info)
-{
- Ecore_Con_Server *obj = data;
- int curstate = 0;
- int broadcast = 1;
- const char *memerr = NULL;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- errno = 0;
- if (!net_info) /* error message has already been handled */
- {
- svr->delete_me = EINA_TRUE;
- goto error;
- }
-
- svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
- net_info->info.ai_protocol);
-#ifdef _WIN32
- if (svr->fd == INVALID_SOCKET) goto error;
-
- if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
-#else
- if (svr->fd < 0) goto error;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
-#endif
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_BROADCAST)
- {
- if (setsockopt(svr->fd, SOL_SOCKET, SO_BROADCAST,
- (const void *)&broadcast,
- sizeof(broadcast)) < 0)
- {
- goto error;
- }
- }
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR,
- (const void *)&curstate, sizeof(curstate)) < 0)
- goto error;
-
- if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
- goto error;
-
- svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
- _ecore_con_cl_udp_handler, obj, NULL, NULL);
-
- if (!svr->fd_handler)
- {
- memerr = "Memory allocation failure";
- goto error;
- }
-
- if ((!svr->ecs) || (svr->ecs->lookup))
- svr->ip = eina_stringshare_add(net_info->ip);
-
- return;
-
-error:
- if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
- ecore_con_ssl_server_shutdown(obj);
- _ecore_con_server_kill(obj);
-}
-
-static Ecore_Con_State
-svr_try_connect_plain(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int res;
- int so_err = 0;
- socklen_t size = sizeof(int);
-
- res = getsockopt(svr->fd, SOL_SOCKET, SO_ERROR, (void *)&so_err, &size);
-#ifdef _WIN32
- if (res == SOCKET_ERROR)
- so_err = WSAGetLastError();
-
- if ((so_err == WSAEINPROGRESS) && !svr->delete_me)
- return ECORE_CON_INPROGRESS;
-
-#else
- if (res < 0)
- so_err = errno;
-
- if ((so_err == EINPROGRESS) && !svr->delete_me)
- return ECORE_CON_INPROGRESS;
-
-#endif
-
- if (so_err)
- {
- /* we lost our server! */
- ecore_con_event_server_error(obj, strerror(so_err));
- DBG("Connection lost: %s", strerror(so_err));
- _ecore_con_server_kill(obj);
- return ECORE_CON_DISCONNECTED;
- }
-
- if ((!svr->delete_me) && (!svr->handshaking) && svr->connecting)
- {
- if (svr->ecs)
- {
- if (ecore_con_socks_svr_init(obj))
- return ECORE_CON_INPROGRESS;
- }
- else
- ecore_con_event_server_add(obj);
- }
-
- if (svr->fd_handler)
- {
- if (svr->buf)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- else
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- }
-
- if (!svr->delete_me)
- return ECORE_CON_CONNECTED;
- else
- return ECORE_CON_DISCONNECTED;
-}
-
-static const char *
-_ecore_con_pretty_ip(struct sockaddr *client_addr)
-{
-#ifndef HAVE_IPV6
- char ipbuf[INET_ADDRSTRLEN + 1];
-#else
- char ipbuf[INET6_ADDRSTRLEN + 1];
-#endif
- int family = client_addr->sa_family;
- void *src;
-
- switch (family)
- {
- case AF_INET:
- src = &(((struct sockaddr_in *)client_addr)->sin_addr);
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6:
- src = &(((struct sockaddr_in6 *)client_addr)->sin6_addr);
-
- if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src))
- {
- family = AF_INET;
- src = (char *)src + 12;
- }
- break;
-
-#endif
- default:
- return eina_stringshare_add("0.0.0.0");
- }
-
- if (!inet_ntop(family, src, ipbuf, sizeof(ipbuf)))
- return eina_stringshare_add("0.0.0.0");
-
- ipbuf[sizeof(ipbuf) - 1] = 0;
- return eina_stringshare_add(ipbuf);
-}
-
-static Eina_Bool
-_ecore_con_svr_tcp_handler(void *data,
- Ecore_Fd_Handler *fd_handler EINA_UNUSED)
-{
- Ecore_Con_Server *svr_obj = data;
- Ecore_Con_Client *obj = NULL;
- unsigned char client_addr[256];
- unsigned int client_addr_len;
- const char *clerr = NULL;
- Efl_Network_Server_Data *svr = efl_data_scope_get(svr_obj, EFL_NETWORK_SERVER_CLASS);
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- if (svr->delete_me)
- return ECORE_CALLBACK_RENEW;
-
- if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
- (svr->client_count >= (unsigned int)svr->client_limit))
- return ECORE_CALLBACK_RENEW;
-
- /* a new client */
-
- obj = efl_add(EFL_NETWORK_CLIENT_CLASS, NULL);
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- {
- ecore_con_event_server_error(svr_obj, "Memory allocation failure when attempting to add a new client");
- return ECORE_CALLBACK_RENEW;
- }
- cl->host_server = svr_obj;
-
- client_addr_len = sizeof(client_addr);
- memset(&client_addr, 0, client_addr_len);
- cl->fd = accept(svr->fd, (struct sockaddr *)&client_addr, (socklen_t *)&client_addr_len);
-#ifdef _WIN32
- if (cl->fd == INVALID_SOCKET) goto error;
-#else
- if (cl->fd < 0) goto error;
-#endif
- if ((svr->client_limit >= 0) && (svr->reject_excess_clients) &&
- (svr->client_count >= (unsigned int)svr->client_limit))
- {
- clerr = "Maximum client limit reached";
- goto error;
- }
-
-#ifdef _WIN32
- if (ioctlsocket(cl->fd, FIONBIO, &mode)) goto error;
-#else
- if (fcntl(cl->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(cl->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
-#endif
- cl->fd_handler = ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
- _ecore_con_svr_cl_handler, obj, NULL, NULL);
- if (!cl->fd_handler) goto error;
-
- if ((!svr->upgrade) && (svr->type & ECORE_CON_SSL))
- {
- cl->handshaking = EINA_TRUE;
- cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
- if (ecore_con_ssl_client_init(obj))
- goto error;
- }
-
- cl->client_addr = malloc(client_addr_len);
- if (!cl->client_addr)
- {
- clerr = "Memory allocation failure when attempting to add a new client";
- goto error;
- }
- cl->client_addr_len = client_addr_len;
- memcpy(cl->client_addr, &client_addr, client_addr_len);
-
- svr->clients = eina_list_append(svr->clients, obj);
- svr->client_count++;
-
- if ((!cl->delete_me) && (!cl->handshaking))
- ecore_con_event_client_add(obj);
-
- return ECORE_CALLBACK_RENEW;
-
-error:
- if (cl->fd_handler) ecore_main_fd_handler_del(cl->fd_handler);
- if (cl->fd != INVALID_SOCKET) closesocket(cl->fd);
- {
- Ecore_Event *ev;
-
- EINA_LIST_FREE(cl->event_count, ev)
- {
- svr->event_count = eina_list_remove(svr->event_count, ev);
- ecore_event_del(ev);
- }
- }
- efl_del(obj);
- if (clerr || errno) ecore_con_event_server_error(svr_obj, clerr ? : strerror(errno));
- return ECORE_CALLBACK_RENEW;
-}
-
-static void
-_ecore_con_cl_read(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int num = 0;
- Eina_Bool lost_server = EINA_TRUE;
- unsigned char buf[READBUFSIZ];
-
- DBG("svr=%p", svr);
-
- /* only possible with non-ssl connections */
- if (svr->connecting && (svr_try_connect_plain(obj) != ECORE_CON_CONNECTED))
- return;
-
- if (svr->handshaking && (!svr->ecs_state))
- {
- DBG("Continuing ssl handshake");
- if (!ecore_con_ssl_server_init(obj))
- lost_server = EINA_FALSE;
- _ecore_con_server_timer_update(obj);
- }
-
- if (svr->ecs_state || !(svr->type & ECORE_CON_SSL))
- {
- errno = 0;
- num = recv(svr->fd, (char *)buf, sizeof(buf), 0);
-
- /* 0 is not a valid return value for a tcp socket */
-#ifdef _WIN32
- if ((num > 0) || ((num < 0) && (WSAGetLastError() == WSAEWOULDBLOCK)))
-#else
- if ((num > 0) || ((num < 0) && (errno == EAGAIN)))
-#endif
- lost_server = EINA_FALSE;
- else if (num < 0)
- ecore_con_event_server_error(obj, strerror(errno));
- }
- else
- {
- num = ecore_con_ssl_server_read(obj, buf, sizeof(buf));
- /* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
- if (num >= 0)
- lost_server = EINA_FALSE;
- }
-
- if ((!svr->delete_me) && (num > 0))
- {
- if (svr->ecs_state)
- ecore_con_socks_read(obj, buf, num);
- else
- ecore_con_event_server_data(obj, buf, num, EINA_TRUE);
- }
-
- if (lost_server)
- _ecore_con_server_kill(obj);
-}
-
-static Eina_Bool
-_ecore_con_cl_handler(void *data,
- Ecore_Fd_Handler *fd_handler)
-{
- Ecore_Con_Server *obj = data;
- Eina_Bool want_read, want_write;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
-
- if (svr->delete_me)
- return ECORE_CALLBACK_RENEW;
-
- if (svr->delete_me)
- return ECORE_CALLBACK_RENEW;
-
- want_read = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ);
- want_write = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE);
-
- if ((!svr->ecs_state) && svr->handshaking && (want_read || want_write))
- {
- DBG("Continuing ssl handshake: preparing to %s...", want_read ? "read" : "write");
-#ifdef ISCOMFITOR
- if (want_read)
- {
- char buf[READBUFSIZ];
- ssize_t len;
- len = recv(svr->fd, (char *)buf, sizeof(buf), MSG_DONTWAIT | MSG_PEEK);
- DBG("%zu bytes in buffer", len);
- }
-#endif
- if (ecore_con_ssl_server_init(obj))
- {
- DBG("ssl handshaking failed!");
- svr->handshaking = EINA_FALSE;
- }
- else if (!svr->ssl_state)
- ecore_con_event_server_add(obj);
- return ECORE_CALLBACK_RENEW;
- }
- if (svr->ecs && svr->ecs_state && (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) && (!svr->ecs_buf))
- {
- if (svr->ecs_state < ECORE_CON_PROXY_STATE_INIT)
- {
- INF("PROXY STATE++");
- svr->ecs_state++;
- }
- if (ecore_con_socks_svr_init(obj)) return ECORE_CALLBACK_RENEW;
- }
- if (want_read)
- _ecore_con_cl_read(obj);
- else if (want_write) /* only possible with non-ssl connections */
- {
- if (svr->connecting && (!svr_try_connect_plain(obj)) && (!svr->ecs_state))
- return ECORE_CALLBACK_RENEW;
-
- _ecore_con_server_flush(obj);
- }
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static Eina_Bool
-_ecore_con_cl_udp_handler(void *data,
- Ecore_Fd_Handler *fd_handler)
-{
- unsigned char buf[READBUFSIZ];
- int num;
- Ecore_Con_Server *obj = data;
- Eina_Bool want_read, want_write;
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
-
- want_read = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ);
- want_write = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE);
-
- if (svr->delete_me || ((!want_read) && (!want_write)))
- return ECORE_CALLBACK_RENEW;
-
- if (want_write)
- {
- _ecore_con_server_flush(obj);
- return ECORE_CALLBACK_RENEW;
- }
-
- num = recv(svr->fd, (char *)buf, READBUFSIZ, 0);
-
- if ((!svr->delete_me) && (num > 0))
- ecore_con_event_server_data(obj, buf, num, EINA_TRUE);
-
- if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
- {
- ecore_con_event_server_error(obj, strerror(errno));
- _ecore_con_server_kill(obj);
- }
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static Eina_Bool
-_ecore_con_svr_udp_handler(void *data,
- Ecore_Fd_Handler *fd_handler)
-{
- unsigned char buf[READBUFSIZ];
- unsigned char client_addr[256];
- socklen_t client_addr_len = sizeof(client_addr);
- int num;
- Ecore_Con_Server *svr_obj = data;
- Ecore_Con_Client *obj = NULL;
-#ifdef _WIN32
- u_long mode = 1;
-#endif
-
- Efl_Network_Server_Data *svr = efl_data_scope_get(svr_obj, EFL_NETWORK_SERVER_CLASS);
- if (svr->delete_me)
- return ECORE_CALLBACK_RENEW;
-
- if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
- return ECORE_CALLBACK_RENEW;
-
- if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
- return ECORE_CALLBACK_RENEW;
-
-#ifdef _WIN32
- if (!ioctlsocket(svr->fd, FIONBIO, &mode))
- num = recvfrom(svr->fd, (char *)buf, sizeof(buf), 0,
- (struct sockaddr *)&client_addr,
- &client_addr_len);
-
-#else
- num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT,
- (struct sockaddr *)&client_addr,
- &client_addr_len);
-#endif
-
- if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
- {
- ecore_con_event_server_error(svr_obj, strerror(errno));
- if (!svr->delete_me)
- ecore_con_event_client_del(NULL);
- _ecore_con_server_kill(svr_obj);
- return ECORE_CALLBACK_CANCEL;
- }
-
-/* Create a new client for use in the client data event */
- obj = efl_add(EFL_NETWORK_CLIENT_CLASS, NULL);
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- EINA_SAFETY_ON_NULL_RETURN_VAL(cl, ECORE_CALLBACK_RENEW);
-
- cl->host_server = svr_obj;
- cl->fd = INVALID_SOCKET;
- cl->client_addr = malloc(client_addr_len);
- if (!cl->client_addr)
- {
- free(cl);
- return ECORE_CALLBACK_RENEW;
- }
- cl->client_addr_len = client_addr_len;
-
- memcpy(cl->client_addr, &client_addr, client_addr_len);
- svr->clients = eina_list_append(svr->clients, obj);
- svr->client_count++;
-
- ecore_con_event_client_add(obj);
- ecore_con_event_client_data(obj, buf, num, EINA_TRUE);
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static void
-_ecore_con_svr_cl_read(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int num = 0;
- Eina_Bool lost_client = EINA_TRUE;
- unsigned char buf[READBUFSIZ];
-
- DBG("cl=%p", cl);
-
- if (cl->handshaking)
- {
- /* add an extra handshake attempt just before read, even though
- * read also attempts to handshake, to try to finish sooner
- */
- if (ecore_con_ssl_client_init(obj))
- lost_client = EINA_FALSE;
-
- _ecore_con_cl_timer_update(obj);
- }
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (!(host_server->type & ECORE_CON_SSL) && (!cl->upgrade))
- {
- num = recv(cl->fd, (char *)buf, sizeof(buf), 0);
-
- /* 0 is not a valid return value for a tcp socket */
- if ((num > 0) || ((num < 0) && ((errno == EAGAIN) || (errno == EINTR))))
- lost_client = EINA_FALSE;
- else if (num < 0)
- ecore_con_event_client_error(obj, strerror(errno));
- }
- else
- {
- num = ecore_con_ssl_client_read(obj, buf, sizeof(buf));
- /* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
- if (num >= 0)
- lost_client = EINA_FALSE;
- }
-
- if ((!cl->delete_me) && (num > 0))
- ecore_con_event_client_data(obj, buf, num, EINA_TRUE);
-
- if (lost_client) _ecore_con_client_kill(obj);
-}
-
-static Eina_Bool
-_ecore_con_svr_cl_handler(void *data,
- Ecore_Fd_Handler *fd_handler)
-{
- Ecore_Con_Client *obj = data;
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
-
- if (cl->delete_me)
- return ECORE_CALLBACK_RENEW;
-
- if (cl->handshaking && ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ | ECORE_FD_WRITE))
- {
- if (ecore_con_ssl_client_init(obj))
- {
- DBG("ssl handshaking failed!");
- _ecore_con_client_kill(obj);
- return ECORE_CALLBACK_RENEW;
- }
- else if (!cl->ssl_state)
- ecore_con_event_client_add(obj);
- }
- else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
- _ecore_con_svr_cl_read(obj);
-
- else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
- _ecore_con_client_flush(obj);
-
- return ECORE_CALLBACK_RENEW;
-}
-
-static void
-_ecore_con_server_flush(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int count;
- size_t num;
- size_t buf_len;
- size_t *buf_offset;
- const unsigned char *buf;
- Eina_Binbuf *buf_p;
-
- DBG("(svr=%p,buf=%p)", svr, svr->buf);
- if (!svr->fd_handler) return;
-#ifdef _WIN32
- if (ecore_con_local_win32_server_flush(obj))
- return;
-#endif
-
- if ((!svr->buf) && (!svr->ecs_buf))
- {
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- return;
- }
-
- if (svr->buf)
- {
- buf_p = svr->buf;
- buf_offset = &(svr->write_buf_offset);
- }
- else
- {
- buf_p = svr->ecs_buf;
- buf_offset = &(svr->ecs_buf_offset);
- }
- buf = eina_binbuf_string_get(buf_p);
- buf_len = eina_binbuf_length_get(buf_p);
- num = buf_len - *buf_offset;
-
- /* check whether we need to write anything at all.
- * we must not write zero bytes with SSL_write() since it
- * causes undefined behaviour
- */
- /* we thank Tommy[D] for needing to check negative buffer sizes
- * here because his system is amazing.
- */
- if (num <= 0) return;
-
- if ((!svr->ecs_state) && svr->handshaking)
- {
- DBG("Continuing ssl handshake");
- if (ecore_con_ssl_server_init(obj))
- _ecore_con_server_kill(obj);
- _ecore_con_server_timer_update(obj);
- return;
- }
-
- if (svr->ecs_state || (!(svr->type & ECORE_CON_SSL)))
- count = send(svr->fd, (const char *)buf + *buf_offset, num, 0);
- else
- count = ecore_con_ssl_server_write(obj, buf + *buf_offset, num);
-
-#ifdef _WIN32
- if (count == SOCKET_ERROR)
- {
- switch (WSAGetLastError())
- {
- case WSAEINTR:
- case WSAEINPROGRESS:
- case WSAEWOULDBLOCK:
- break;
- default:
- {
- LPTSTR s;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&s, 0, NULL);
- ecore_con_event_server_error(obj, (char *)s);
- free(s);
- _ecore_con_server_kill(obj);
- }
- }
- }
-#else
- if (count < 0)
- {
- if ((errno != EAGAIN) && (errno != EINTR))
- {
- ecore_con_event_server_error(obj, strerror(errno));
- _ecore_con_server_kill(obj);
- }
- return;
- }
-#endif
-
-
- if (count && (!svr->ecs_state)) ecore_con_event_server_write(obj, count);
-
- if (!eina_binbuf_remove(buf_p, 0, count))
- *buf_offset += count;
- else
- {
- *buf_offset = 0;
- buf_len -= count;
- }
- if (*buf_offset >= buf_len)
- {
- *buf_offset = 0;
- eina_binbuf_free(buf_p);
-
- if (svr->ecs_buf)
- {
- svr->ecs_buf = NULL;
- INF("PROXY STATE++");
- svr->ecs_state++;
- }
- else
- {
- svr->buf = NULL;
-#ifdef TCP_CORK
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK)
- {
- int state = 0;
- if (setsockopt(svr->fd, IPPROTO_TCP, TCP_CORK, (char *)&state, sizeof(int)) < 0)
- /* realistically this isn't anything serious so we can just log and continue */
- ERR("uncorking failed! %s", strerror(errno));
- }
-#endif
- }
- if (svr->fd_handler)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- }
- else if (((unsigned int)count < num) && svr->fd_handler)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
-}
-
-static void
-_ecore_con_client_flush(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int count = 0;
- size_t num = 0;
-
- if (!cl->fd_handler) return;
-#ifdef _WIN32
- if (ecore_con_local_win32_client_flush(obj))
- return;
-#endif
-
- if (!cl->buf)
- {
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- return;
- }
-
- if (cl->handshaking)
- {
- if (ecore_con_ssl_client_init(obj))
- count = -1;
-
- _ecore_con_cl_timer_update(obj);
- }
-
- if (!count)
- {
- if (!cl->buf) return;
- num = eina_binbuf_length_get(cl->buf) - cl->buf_offset;
- if (num <= 0) return;
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (!(host_server->type & ECORE_CON_SSL) && (!cl->upgrade))
- count = send(cl->fd, (char *)eina_binbuf_string_get(cl->buf) + cl->buf_offset, num, 0);
- else
- count = ecore_con_ssl_client_write(obj, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num);
- }
-
- if (count < 0)
- {
- if ((errno != EAGAIN) && (errno != EINTR) && (!cl->delete_me))
- {
- ecore_con_event_client_error(obj, strerror(errno));
- _ecore_con_client_kill(obj);
- }
-
- return;
- }
-
- if (count) ecore_con_event_client_write(obj, count);
- cl->buf_offset += count, num -= count;
- if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
- {
- cl->buf_offset = 0;
- eina_binbuf_free(cl->buf);
- cl->buf = NULL;
-#ifdef TCP_CORK
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK)
- {
- int state = 0;
- if (setsockopt(cl->fd, IPPROTO_TCP, TCP_CORK, (char *)&state, sizeof(int)) < 0)
- /* realistically this isn't anything serious so we can just log and continue */
- ERR("uncorking failed! %s", strerror(errno));
- }
-#endif
- if (cl->fd_handler)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- }
- else if (cl->fd_handler)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
-}
-
-static void
-_ecore_con_event_client_add_free(Ecore_Con_Server *obj,
- void *ev)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Client_Add *e;
-
- e = ev;
- if (e->client)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
- Eina_Bool svrfreed = EINA_FALSE;
-
- if ((svr) && (cl))
- {
- cl->event_count = eina_list_remove(cl->event_count, e);
- if (cl->host_server)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (host_server)
- host_server->event_count = eina_list_remove(host_server->event_count, ev);
- if ((!svr->event_count) && (svr->delete_me))
- {
- _ecore_con_server_free(obj);
- svrfreed = EINA_TRUE;
- }
- }
- if (!svrfreed)
- {
- if ((!cl->event_count) && (cl->delete_me))
- ecore_con_client_del(e->client);
- }
- }
- }
-
- ecore_con_event_client_add_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_client_del_free(Ecore_Con_Server *obj,
- void *ev)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Client_Del *e;
-
- e = ev;
- if (e->client)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
- Eina_Bool svrfreed = EINA_FALSE;
-
- if ((svr) && (cl))
- {
- cl->event_count = eina_list_remove(cl->event_count, e);
- if (cl->host_server)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (host_server)
- host_server->event_count = eina_list_remove(host_server->event_count, ev);
- if ((!svr->event_count) && (svr->delete_me))
- {
- _ecore_con_server_free(obj);
- svrfreed = EINA_TRUE;
- }
- }
- if (!svrfreed)
- {
- if (!cl->event_count)
- _ecore_con_client_free(e->client);
- }
- }
- }
- ecore_con_event_client_del_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_client_write_free(Ecore_Con_Server *obj,
- Ecore_Con_Event_Client_Write *e)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (e->client)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
- Eina_Bool svrfreed = EINA_FALSE;
-
- if ((svr) && (cl))
- {
- cl->event_count = eina_list_remove(cl->event_count, e);
- if (cl->host_server)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (host_server)
- host_server->event_count = eina_list_remove(host_server->event_count, e);
- if ((!svr->event_count) && (svr->delete_me))
- {
- _ecore_con_server_free(obj);
- svrfreed = EINA_TRUE;
- }
- }
- if (!svrfreed)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (((!cl->event_count) && (cl->delete_me)) ||
- ((cl->host_server &&
- ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP ||
- (host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST))))
- ecore_con_client_del(e->client);
- }
- }
- }
- ecore_con_event_client_write_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_client_data_free(Ecore_Con_Server *obj,
- void *ev)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- Ecore_Con_Event_Client_Data *e;
-
- e = ev;
- if (e->client)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
- Eina_Bool svrfreed = EINA_FALSE;
-
- if ((svr) && (cl))
- {
- cl->event_count = eina_list_remove(cl->event_count, e);
- if (cl->host_server)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (host_server)
- host_server->event_count = eina_list_remove(host_server->event_count, ev);
- }
- if ((!svr->event_count) && (svr->delete_me))
- {
- _ecore_con_server_free(obj);
- svrfreed = EINA_TRUE;
- }
- if (!svrfreed)
- {
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (((!cl->event_count) && (cl->delete_me)) ||
- ((cl->host_server &&
- ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP ||
- (host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST))))
- ecore_con_client_del(e->client);
- }
- }
- }
- free(e->data);
- ecore_con_event_client_data_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_server_add_free(void *data EINA_UNUSED,
- void *ev)
-{
- Ecore_Con_Event_Server_Add *e;
-
- e = ev;
- if (e->server)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
- if (svr)
- {
- svr->event_count = eina_list_remove(svr->event_count, ev);
- if ((!svr->event_count) && (svr->delete_me))
- _ecore_con_server_free(e->server);
- }
- }
- ecore_con_event_server_add_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_server_del_free(void *data EINA_UNUSED,
- void *ev)
-{
- Ecore_Con_Event_Server_Del *e;
-
- e = ev;
- if (e->server)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
- if (svr)
- {
- svr->event_count = eina_list_remove(svr->event_count, ev);
- if (!svr->event_count)
- _ecore_con_server_free(e->server);
- }
- }
- ecore_con_event_server_del_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_server_write_free(void *data EINA_UNUSED,
- Ecore_Con_Event_Server_Write *e)
-{
- if (e->server)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
- if (svr)
- {
- svr->event_count = eina_list_remove(svr->event_count, e);
- if ((!svr->event_count) && (svr->delete_me))
- _ecore_con_server_free(e->server);
- }
- }
- ecore_con_event_server_write_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_server_data_free(void *data EINA_UNUSED,
- void *ev)
-{
- Ecore_Con_Event_Server_Data *e;
-
- e = ev;
- if (e->server)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
- if (svr)
- {
- svr->event_count = eina_list_remove(svr->event_count, ev);
- if ((!svr->event_count) && (svr->delete_me))
- _ecore_con_server_free(e->server);
- }
- }
-
- free(e->data);
- ecore_con_event_server_data_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_server_error_free(void *data EINA_UNUSED, Ecore_Con_Event_Server_Error *e)
-{
- if (e->server)
- {
- Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
- if (svr)
- {
- svr->event_count = eina_list_remove(svr->event_count, e);
- if ((!svr->event_count) && (svr->delete_me))
- _ecore_con_server_free(e->server);
- }
- }
- free(e->error);
- ecore_con_event_server_error_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_event_client_error_free(Ecore_Con_Server *obj, Ecore_Con_Event_Client_Error *e)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (e->client)
- {
- Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
- Eina_Bool svrfreed = EINA_FALSE;
-
- if ((svr) && (cl))
- {
- if (eina_list_data_find(svr->clients, e->client))
- {
- cl->event_count = eina_list_remove(cl->event_count, e);
- if ((!cl->event_count) && (cl->delete_me))
- {
- _ecore_con_client_free(e->client);
- svrfreed = EINA_TRUE;
- }
- }
- svr->event_count = eina_list_remove(svr->event_count, e);
- if (!svrfreed)
- {
- if ((!svr->event_count) && (svr->delete_me))
- _ecore_con_server_free(obj);
- }
- }
- }
- free(e->error);
- ecore_con_event_client_error_free(e);
- _ecore_con_event_count--;
- if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
- ecore_con_mempool_shutdown();
-}
-
-static void
-_ecore_con_lookup_done(void *data,
- Ecore_Con_Info *infos)
-{
- Ecore_Con_Server *obj = data;
- Ecore_Con_Lookup *lk;
-
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return;
- lk = svr->data;
-
- if (infos)
- lk->done_cb(infos->info.ai_canonname, infos->ip,
- infos->info.ai_addr, infos->info.ai_addrlen,
- (void *)lk->data);
- else
- lk->done_cb(NULL, NULL, NULL, 0, (void *)lk->data);
-
- free(lk);
}
-#include "efl_network.eo.c"
-#include "efl_network_client.eo.c"
-#include "efl_network_server.eo.c"
-#include "efl_network_connector.eo.c"
#ifndef _WIN32
Eina_Bool
diff --git a/src/lib/ecore_con/ecore_con_alloc.c b/src/lib/ecore_con/ecore_con_alloc.c
index 1c04a557bc..b5d49b9486 100644
--- a/src/lib/ecore_con/ecore_con_alloc.c
+++ b/src/lib/ecore_con/ecore_con_alloc.c
@@ -35,7 +35,9 @@ GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
+GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Upgrade, ecore_con_event_server_upgrade);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
+GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Upgrade, ecore_con_event_client_upgrade);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
@@ -48,7 +50,9 @@ static Ecore_Con_Mempool *mempool_array[] = {
&ecore_con_event_client_write_mp,
&ecore_con_event_client_data_mp,
&ecore_con_event_server_error_mp,
+ &ecore_con_event_server_upgrade_mp,
&ecore_con_event_client_error_mp,
+ &ecore_con_event_client_upgrade_mp,
&ecore_con_event_server_add_mp,
&ecore_con_event_server_del_mp,
&ecore_con_event_server_write_mp,
diff --git a/src/lib/ecore_con/ecore_con_eet.c b/src/lib/ecore_con/ecore_con_eet.c
index 1cf9954ebc..aed9b9fc11 100644
--- a/src/lib/ecore_con/ecore_con_eet.c
+++ b/src/lib/ecore_con/ecore_con_eet.c
@@ -17,6 +17,9 @@
#include <Eina.h>
+#include "Ecore.h"
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
#include "Ecore_Con_Eet.h"
#define ECORE_CON_EET_RAW_MAGIC 0xDEAD007
@@ -699,7 +702,7 @@ _ecore_con_eet_base_efl_object_finalize(Eo *obj, Ecore_Con_Eet_Base_Data *pd)
EOLIAN static void
_ecore_con_eet_base_server_set(Eo *obj EINA_UNUSED, Ecore_Con_Eet_Base_Data *pd, Ecore_Con_Server *data)
{
- if (!efl_isa(data, EFL_NETWORK_SERVER_CLASS))
+ if (!ecore_con_server_check(data))
return;
pd->server = data;
diff --git a/src/lib/ecore_con/ecore_con_eet_base.eo b/src/lib/ecore_con/ecore_con_eet_base.eo
index fcbc83574f..9f57ea6e18 100644
--- a/src/lib/ecore_con/ecore_con_eet_base.eo
+++ b/src/lib/ecore_con/ecore_con_eet_base.eo
@@ -1,5 +1,4 @@
-import efl_network_server;
-
+struct @extern Ecore_Con_Server;
type @extern Ecore_Con_Eet_Data_Cb: __undefined_type; [[Ecore connection eet data callback type]] /* FIXME: function pointers not supported. */
type @extern Ecore_Con_Eet_Raw_Data_Cb: __undefined_type; [[Ecore connection eet raw data callback type]]/* FIXME: function pointers not supported. */
@@ -19,7 +18,7 @@ class Ecore.Con.Eet.Base (Efl.Object) {
get {
}
values {
- data: Efl.Network.Server; [[Server object]]
+ data: ptr(Ecore_Con_Server); [[Server object]]
}
}
@property data_callback {
diff --git a/src/lib/ecore_con/ecore_con_info.c b/src/lib/ecore_con/ecore_con_info.c
deleted file mode 100644
index 5038817c61..0000000000
--- a/src/lib/ecore_con/ecore_con_info.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * getaddrinfo with callback
- *
- * man getaddrinfo
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef __OpenBSD__
-# include <sys/types.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-
-#include <errno.h>
-
-#include "Ecore.h"
-#include "ecore_private.h"
-#include "ecore_con_private.h"
-
-typedef struct _CB_Data CB_Data;
-
-struct _CB_Data
-{
- EINA_INLIST;
- Ecore_Con_Info_Cb cb_done;
- void *data;
- Ecore_Thread *thread;
- struct addrinfo hints;
- Ecore_Con_Info *result;
- int error;
- char service[NI_MAXSERV];
- char name[NI_MAXHOST];
-};
-
-static void _ecore_con_info_slave_free (CB_Data *cbdata);
-static void _ecore_con_info_slave_result(void *data, Ecore_Thread *th);
-static void _ecore_con_info_slave_cancel(void *data, Ecore_Thread *th);
-static void _ecore_con_info_slave_lookup(void *data, Ecore_Thread *th);
-
-static int info_init = 0;
-static CB_Data *info_slaves = NULL;
-
-int
-ecore_con_info_init(void)
-{
- info_init++;
- return info_init;
-}
-
-int
-ecore_con_info_shutdown(void)
-{
- info_init--;
- if (info_init == 0)
- {
- while (info_slaves)
- {
- CB_Data *cbdata;
-
- cbdata = info_slaves;
- info_slaves = (CB_Data *)eina_inlist_remove
- (EINA_INLIST_GET(info_slaves), EINA_INLIST_GET(info_slaves));
- ecore_thread_cancel(cbdata->thread);
- }
- }
- return info_init;
-}
-
-static void
-_hints_fill(struct addrinfo *hints, int flags, int proto)
-{
- memset(hints, 0, sizeof(struct addrinfo));
- hints->ai_family = AF_UNSPEC;
- hints->ai_flags = flags;
- if (proto == IPPROTO_TCP) hints->ai_socktype = SOCK_STREAM;
- else hints->ai_socktype = SOCK_DGRAM;
- hints->ai_protocol = proto;
-}
-
-int
-ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data)
-{
- struct addrinfo hints;
- _hints_fill(&hints, AI_CANONNAME, IPPROTO_TCP);
- return ecore_con_info_get(svr, done_cb, data, &hints);
-}
-
-int
-ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data)
-{
- struct addrinfo hints;
- _hints_fill(&hints, AI_PASSIVE, IPPROTO_TCP);
- return ecore_con_info_get(svr, done_cb, data, &hints);
-}
-
-int
-ecore_con_info_udp_connect(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data)
-{
- struct addrinfo hints;
- _hints_fill(&hints, AI_CANONNAME, IPPROTO_UDP);
- return ecore_con_info_get(svr, done_cb, data, &hints);
-}
-
-int
-ecore_con_info_udp_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data)
-{
- struct addrinfo hints;
- _hints_fill(&hints, AI_PASSIVE, IPPROTO_UDP);
- return ecore_con_info_get(svr, done_cb, data, &hints);
-}
-
-int
-ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data)
-{
- struct addrinfo hints;
- _hints_fill(&hints, 0, IPPROTO_UDP);
- return ecore_con_info_get(svr, done_cb, data, &hints);
-}
-
-EAPI int
-ecore_con_info_get(Ecore_Con_Server *obj,
- Ecore_Con_Info_Cb done_cb,
- void *data,
- struct addrinfo *hints)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- CB_Data *cbdata;
-
- if (!svr) return 0;
- cbdata = calloc(1, sizeof(CB_Data));
- if (!cbdata)
- {
- ecore_con_event_server_error(obj, "Memory allocation failure");
- return 0;
- }
-
- cbdata->cb_done = done_cb;
- cbdata->data = data;
- cbdata->hints = *hints;
- cbdata->thread = ecore_thread_run(_ecore_con_info_slave_lookup,
- _ecore_con_info_slave_result,
- _ecore_con_info_slave_cancel,
- cbdata);
- if (!cbdata->thread)
- {
- free(cbdata);
- ecore_con_event_server_error(obj, "Memory allocation failure");
- return 0;
- }
- eina_convert_itoa(svr->ecs ? svr->ecs->port : svr->port, cbdata->service);
- strncpy(cbdata->name, svr->ecs ? svr->ecs->ip : svr->name, NI_MAXHOST - 1);
- cbdata->name[NI_MAXHOST - 1] = 0;
- info_slaves = (CB_Data *)eina_inlist_append(EINA_INLIST_GET(info_slaves),
- EINA_INLIST_GET(cbdata));
- svr->infos = eina_list_append(svr->infos, cbdata);
- return 1;
-}
-
-void
-ecore_con_info_data_clear(void *info)
-{
- CB_Data *cbdata = info;
- cbdata->data = NULL;
-}
-
-static void
-_ecore_con_info_slave_free(CB_Data *cbdata)
-{
- if (info_slaves)
- info_slaves = (CB_Data *)eina_inlist_remove(EINA_INLIST_GET(info_slaves),
- EINA_INLIST_GET(cbdata));
- if (cbdata->result) free(cbdata->result);
- cbdata->result = NULL;
- if (cbdata->data) ecore_con_server_infos_del(cbdata->data, cbdata);
- cbdata->data = NULL;
- free(cbdata);
-}
-
-static void
-_ecore_con_info_slave_result(void *data, Ecore_Thread *th EINA_UNUSED)
-{
- CB_Data *cbdata = data;
-
- if (cbdata->result) // lookup ok
- {
- if (cbdata->data) cbdata->cb_done(cbdata->data, cbdata->result);
- }
- else // an error occured
- {
- if (cbdata->data)
- {
- char *str = strerror(cbdata->error);
- ecore_con_event_server_error(cbdata->data, str);
- cbdata->cb_done(cbdata->data, NULL);
- }
- }
- if (cbdata->data) ecore_con_server_infos_del(cbdata->data, cbdata);
- cbdata->data = NULL;
- _ecore_con_info_slave_free(cbdata);
-}
-
-static void
-_ecore_con_info_slave_cancel(void *data, Ecore_Thread *th EINA_UNUSED)
-{
- CB_Data *cbdata = data;
- _ecore_con_info_slave_free(cbdata);
-}
-
-static void
-_ecore_con_info_slave_lookup(void *data, Ecore_Thread *th EINA_UNUSED)
-{
- CB_Data *cbdata = data;
- struct addrinfo *result = NULL;
-
- // do lookup, fill cbdata
- if ((!getaddrinfo(cbdata->name, cbdata->service, &(cbdata->hints), &result))
- && (result))
- {
- Ecore_Con_Info *info;
- unsigned int canonname_size = 0, size;
-
- if (result->ai_canonname)
- canonname_size = strlen(result->ai_canonname) + 1;
- size = sizeof(Ecore_Con_Info) + result->ai_addrlen + canonname_size;
- info = calloc(1, size);
- if (info)
- {
- char hbuf[NI_MAXHOST] = { 0 }, sbuf[NI_MAXSERV] = { 0 }, *p;
-
- info->size = size;
- memcpy(&(info->info), result, sizeof(struct addrinfo));
- p = ((char *)info) + sizeof(Ecore_Con_Info);
- memcpy(p, result->ai_addr, result->ai_addrlen);
- info->info.ai_addr = (struct sockaddr *)p;
- if (result->ai_canonname)
- {
- p = ((char *)info) + sizeof(Ecore_Con_Info) + result->ai_addrlen;
- memcpy(p, result->ai_canonname, canonname_size);
- info->info.ai_canonname = p;
- }
- // we don't care about multiple entries - take first one then
- info->info.ai_next = NULL;
- if (!getnameinfo(result->ai_addr, result->ai_addrlen,
- hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
- NI_NUMERICHOST | NI_NUMERICSERV))
- {
- memcpy(info->ip, hbuf, sizeof(info->ip));
- memcpy(info->service, sbuf, sizeof(info->service));
- }
- cbdata->result = info;
- }
- if (!cbdata->result) free(info);
- }
- if (!cbdata->result) cbdata->error = errno;
- if (result) freeaddrinfo(result);
-}
diff --git a/src/lib/ecore_con/ecore_con_legacy.c b/src/lib/ecore_con/ecore_con_legacy.c
index 107ccfd41f..cf2210faa8 100644
--- a/src/lib/ecore_con/ecore_con_legacy.c
+++ b/src/lib/ecore_con/ecore_con_legacy.c
@@ -1,15 +1,2516 @@
-/********************************************************************
- * ecore_con_url.eo.c
- *******************************************************************/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+#define ECORE_CON_TYPE 0x0f
+#define ECORE_CON_SSL 0xf0
+#define ECORE_CON_SUPER_SSL 0xf00
+
+/* This file exists solely to provide ABI compatibility */
+
+struct _Ecore_Con_Server
+{
+ ECORE_MAGIC;
+ Eo *dialer;
+ Eo *server;
+ struct {
+ Efl_Future *job;
+ Eo *clients_ctx;
+ Eina_List *certs;
+ Eina_List *privkeys;
+ Eina_List *crls;
+ Eina_List *cafiles;
+ Eina_Stringshare *verify_name;
+ Eina_Bool verify;
+ Eina_Bool verify_basic;
+ Eina_Bool upgrading;
+ Ecore_Con_Type upgrade_type;
+ } ssl;
+ Eina_List *clients;
+ Eina_List *event_count;
+ const void *data;
+ Eina_Stringshare *name;
+ Eina_Stringshare *ip;
+ size_t pending_write;
+ double start_time;
+ double timeout;
+ Ecore_Con_Type type;
+ int port;
+ Eina_Bool want_mcast;
+ Eina_Bool is_dialer;
+ Eina_Bool connecting;
+ Eina_Bool delete_me;
+};
+
+struct _Ecore_Con_Client
+{
+ ECORE_MAGIC;
+ Eo *socket;
+ Ecore_Con_Server *svr;
+ Eina_List *event_count;
+ const void *data;
+ Eina_Stringshare *ip;
+ struct {
+ Efl_Future *job;
+ Eo *ctx;
+ Eina_Bool upgrading;
+ } ssl;
+ size_t pending_write;
+ double start_time;
+ int port;
+ Eina_Bool delete_me;
+};
+
+typedef struct _Ecore_Con_Lookup_Ctx {
+ Ecore_Thread *thread;
+ Ecore_Con_Dns_Cb cb;
+ const void *data;
+} Ecore_Con_Lookup_Ctx;
+
+/* allows delete_me to be true */
+#define ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, ...) \
+ do \
+ { \
+ if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) \
+ { \
+ ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __FUNCTION__); \
+ return __VA_ARGS__; \
+ } \
+ } \
+ while (0)
+
+#define ECORE_CON_SERVER_CHECK_RETURN(svr, ...) \
+ do \
+ { \
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, __VA_ARGS__) ; \
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->delete_me, __VA_ARGS__); \
+ } \
+ while (0)
+
+#define ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, ...) \
+ do \
+ { \
+ if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) \
+ { \
+ ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __FUNCTION__); \
+ return __VA_ARGS__; \
+ } \
+ } \
+ while (0)
+
+#define ECORE_CON_CLIENT_CHECK_RETURN(cl, ...) \
+ do \
+ { \
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, __VA_ARGS__) ; \
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->delete_me, __VA_ARGS__); \
+ } \
+ while (0)
+
+
+/* from ecore_con_alloc.c */
+#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
+ TYPE *Type##_alloc(void); \
+ void Type##_free(TYPE *e);
+
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Add, ecore_con_event_client_add);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Upgrade, ecore_con_event_server_upgrade);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Proxy_Bind, ecore_con_event_proxy_bind);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Upgrade, ecore_con_event_client_upgrade);
+#undef GENERIC_ALLOC_FREE_HEADER
+
+/* shared */
+EAPI int ECORE_CON_EVENT_SERVER_DEL = 0;
+EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
+/* ecore_con_server_add() */
+EAPI int ECORE_CON_EVENT_CLIENT_ADD = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_DEL = 0;
+/* ecore_con_server_connect() */
+EAPI int ECORE_CON_EVENT_SERVER_ADD = 0;
+EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
+EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
+EAPI int ECORE_CON_EVENT_PROXY_BIND = 0; /* we're not supporting proxy bind, keep only for ABI */
+EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0;
+/* for each client from ECORE_CON_EVENT_CLIENT_ADD */
+EAPI int ECORE_CON_EVENT_CLIENT_DATA = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_WRITE = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
+EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0;
+
+static Eina_List *_servers = NULL;
+static Eina_List *_ecore_con_lookups = NULL;
+static int _ecore_con_event_count = 0;
+
+Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
+Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
+
+void
+ecore_con_legacy_init(void)
+{
+ ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new();
+ ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new();
+ ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
+ ECORE_CON_EVENT_CLIENT_WRITE = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
+ ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
+ ECORE_CON_EVENT_PROXY_BIND = ecore_event_type_new();
+ ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new();
+ ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new();
+
+ eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
+ eina_magic_string_set(ECORE_MAGIC_CON_CLIENT, "Ecore_Con_Client");
+ eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
+
+ ecore_con_socks_init();
+}
+
+static void _ecore_con_server_free(Ecore_Con_Server *svr);
+
+void
+ecore_con_legacy_shutdown(void)
+{
+ Eina_List *l, *l2;
+ Ecore_Con_Server *svr;
+ Ecore_Con_Lookup_Ctx *lookup_ctx;
+
+ EINA_LIST_FOREACH_SAFE(_servers, l, l2, svr)
+ {
+ Ecore_Con_Event_Server_Add *ev;
+
+ if (!svr) continue;
+ svr->delete_me = EINA_TRUE;
+ INF("svr %p is dead", svr);
+ /* some pointer hacks here to prevent double frees if people are being stupid */
+ EINA_LIST_FREE(svr->event_count, ev)
+ ev->server = NULL;
+ _ecore_con_server_free(svr);
+ }
+
+ EINA_LIST_FREE(_ecore_con_lookups, lookup_ctx)
+ ecore_thread_cancel(lookup_ctx->thread);
+
+ ecore_con_socks_shutdown();
+ if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
+ else WRN("%d events still exist, leaking ecore_con mempools", _ecore_con_event_count);
+}
+
+/**
+ * @addtogroup Ecore_Con_Client_Group Ecore Connection Client Functions
+ *
+ * Functions that operate on Ecore connection client objects, these
+ * are announced using ECORE_CON_EVENT_CLIENT_ADD by servers created
+ * with ecore_con_server_add().
+ *
+ * @{
+ */
+
+static Efl_Callback_Array_Item *_ecore_con_client_socket_cbs(void);
+static Efl_Callback_Array_Item *_ecore_con_client_socket_ssl_cbs(void);
+
+static void
+_ecore_con_client_socket_close(Ecore_Con_Client *cl)
+{
+ if (!cl->socket) return;
+
+ /* socket may remain alive due other references, we don't own it */
+ efl_event_callback_array_del(cl->socket, _ecore_con_client_socket_cbs(), cl);
+
+ if (!efl_io_closer_closed_get(cl->socket))
+ efl_io_closer_close(cl->socket);
+}
+
+static void
+_ecore_con_client_free(Ecore_Con_Client *cl)
+{
+ cl->delete_me = EINA_TRUE;
+
+ if (cl->svr)
+ cl->svr->clients = eina_list_remove(cl->svr->clients, cl);
+
+ _ecore_con_client_socket_close(cl);
+
+ if (cl->socket)
+ {
+ Eo *inner_socket = efl_io_buffered_stream_inner_io_get(cl->socket);
+ efl_event_callback_array_del(cl->socket, _ecore_con_client_socket_cbs(), cl);
+ if (efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS))
+ efl_event_callback_array_del(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
+
+ if (efl_parent_get(cl->socket) != cl->svr->server)
+ efl_del(cl->socket); /* we own it */
+ else
+ efl_unref(cl->socket);
+ cl->socket = NULL;
+ }
+
+ if (cl->ssl.job) efl_future_cancel(cl->ssl.job);
+
+ if (cl->ssl.ctx)
+ {
+ efl_unref(cl->ssl.ctx);
+ cl->ssl.ctx = NULL;
+ }
+
+ if (cl->event_count) return;
+
+ cl->data = NULL;
+ eina_stringshare_replace(&cl->ip, NULL);
+
+ EINA_MAGIC_SET(cl, ECORE_MAGIC_NONE);
+ free(cl);
+}
+
+/* BEGIN: post of Ecore_Event for ecore_con_server_connect() ************/
+
+static void
+_ecore_con_free_event_client_add(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Add *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if ((!cl->event_count) && (cl->delete_me))
+ _ecore_con_client_free(cl);
+ }
+ ecore_con_event_client_add_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_add(Ecore_Con_Client *cl)
+{
+ Ecore_Con_Event_Client_Add *ev = ecore_con_event_client_add_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->client = cl;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, ev, _ecore_con_free_event_client_add, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_client_free(cl);
+}
+
+static void
+_ecore_con_free_event_client_del(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Del *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if (!cl->event_count)
+ _ecore_con_client_free(cl);
+ else
+ cl->delete_me = EINA_TRUE;
+ }
+ ecore_con_event_client_del_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_del(Ecore_Con_Client *cl)
+{
+ Ecore_Con_Event_Client_Del *ev = ecore_con_event_client_del_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->client = cl;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ /* legacy compatibility: test suite expects NULL pointer for IP */
+ eina_stringshare_replace(&cl->ip, NULL);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, ev, _ecore_con_free_event_client_del, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_client_free(cl);
+}
+
+static void
+_ecore_con_free_event_client_data(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Data *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if ((!cl->event_count) && (cl->delete_me))
+ _ecore_con_client_free(cl);
+ }
+ free(ev->data);
+ ecore_con_event_client_data_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_data(Ecore_Con_Client *cl, Eina_Rw_Slice slice)
+{
+ Ecore_Con_Event_Client_Data *ev = ecore_con_event_client_data_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->client = cl;
+ ev->data = slice.mem;
+ ev->size = slice.len;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, ev, _ecore_con_free_event_client_data, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ free(slice.mem);
+}
+
+static void
+_ecore_con_free_event_client_write(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Write *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if ((!cl->event_count) && (cl->delete_me))
+ _ecore_con_client_free(cl);
+ }
+ ecore_con_event_client_write_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_write(Ecore_Con_Client *cl, size_t size)
+{
+ Ecore_Con_Event_Client_Write *ev = ecore_con_event_client_write_alloc();
+ EINA_SAFETY_ON_NULL_RETURN(ev);
+
+ ev->client = cl;
+ ev->size = size;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_WRITE, ev, _ecore_con_free_event_client_write, NULL);
+ _ecore_con_event_count++;
+}
+
+static void
+_ecore_con_free_event_client_error(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Error *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if ((!cl->event_count) && (cl->delete_me))
+ _ecore_con_client_free(cl);
+ }
+ free(ev->error);
+ ecore_con_event_client_error_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_error(Ecore_Con_Client *cl, const char *err)
+{
+ Ecore_Con_Event_Client_Error *ev = ecore_con_event_client_error_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ INF("cl=%p error from %s: %s", cl, efl_net_socket_address_remote_get(cl->socket), err);
+
+ ev->client = cl;
+ ev->error = err ? strdup(err) : NULL;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_ERROR, ev, _ecore_con_free_event_client_error, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_client_free(cl);
+}
+
+static void
+_ecore_con_free_event_client_upgrade(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Client_Upgrade *ev = event;
+
+ if (ev->client)
+ {
+ Ecore_Con_Client *cl = ev->client;
+ cl->event_count = eina_list_remove(cl->event_count, ev);
+ if ((!cl->event_count) && (cl->delete_me))
+ _ecore_con_client_free(cl);
+ }
+ ecore_con_event_client_upgrade_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_client_upgrade(Ecore_Con_Client *cl)
+{
+ Ecore_Con_Event_Client_Upgrade *ev = ecore_con_event_client_upgrade_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->client = cl;
+ cl->event_count = eina_list_append(cl->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_UPGRADE, ev, _ecore_con_free_event_client_upgrade, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_client_free(cl);
+}
+
+/* END: post of Ecore_Event for ecore_con_server_add() ******************/
+
+static void
+_ecore_con_client_socket_progress(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Client *cl = data;
+ size_t now = efl_io_buffered_stream_pending_write_get(cl->socket);
+
+ if (cl->delete_me) return;
+ if (cl->ssl.upgrading) return;
+
+ if (cl->pending_write == now) return;
+ EINA_SAFETY_ON_TRUE_GOTO(cl->pending_write < now, end); /* forgot to update! */
+
+ _ecore_con_post_event_client_write(cl, cl->pending_write - now);
+
+ end:
+ cl->pending_write = now;
+}
+
+static void
+_ecore_con_client_socket_slice_changed(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Client *cl = data;
+ Eina_Slice ro_slice;
+ Eina_Rw_Slice rw_slice;
+
+ if (cl->delete_me) return;
+ if (cl->ssl.upgrading) return;
+
+ if (!efl_io_buffered_stream_slice_get(cl->socket, &ro_slice)) return;
+ if (ro_slice.len == 0) return;
+
+ rw_slice = eina_slice_dup(ro_slice);
+ efl_io_buffered_stream_clear(cl->socket);
+ _ecore_con_post_event_client_data(cl, rw_slice);
+}
+
+static void
+_ecore_con_client_socket_finished(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Client *cl = data;
+
+ DBG("client %p socket %p finished", cl, cl->socket);
+
+ _ecore_con_client_socket_close(cl);
+
+ _ecore_con_post_event_client_del(cl);
+}
+
+static void
+_ecore_con_client_socket_error(void *data, const Efl_Event *event)
+{
+ Ecore_Con_Client *cl = data;
+ Eina_Error *perr = event->info;
+
+ if (cl->delete_me) return;
+
+ WRN("error client %s: %s", efl_net_socket_address_remote_get(cl->socket), eina_error_msg_get(*perr));
+
+ _ecore_con_post_event_client_error(cl, eina_error_msg_get(*perr));
+ _ecore_con_client_socket_close(cl);
+}
+
+EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_client_socket_cbs,
+ { EFL_IO_BUFFERED_STREAM_EVENT_PROGRESS, _ecore_con_client_socket_progress },
+ { EFL_IO_BUFFERED_STREAM_EVENT_SLICE_CHANGED, _ecore_con_client_socket_slice_changed },
+ { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _ecore_con_client_socket_finished },
+ { EFL_IO_BUFFERED_STREAM_EVENT_ERROR, _ecore_con_client_socket_error });
+
+static Ecore_Con_Client *
+ecore_con_client_add(Ecore_Con_Server *svr, Eo *socket)
+{
+ Ecore_Con_Client *cl;
+ Eo *inner_socket;
+
+ cl = calloc(1, sizeof(Ecore_Con_Client));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cl, NULL);
+
+ cl->socket = efl_ref(socket);
+ cl->svr = svr;
+ cl->start_time = ecore_time_get();
+ cl->port = -1;
+
+ inner_socket = efl_io_buffered_stream_inner_io_get(socket);
+ if (efl_isa(inner_socket, EFL_NET_SOCKET_TCP_CLASS) ||
+ efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS) ||
+ efl_isa(inner_socket, EFL_NET_SERVER_UDP_CLIENT_CLASS))
+ {
+ const char *addr = efl_net_socket_address_remote_get(inner_socket);
+ if (addr)
+ {
+ const char *p;
+ if (addr[0] != '[') p = strchr(addr, ':');
+ else
+ {
+ addr++;
+ p = strchr(addr, ']');
+ }
+ if (p)
+ {
+ const char *portstr = p;
+ if (portstr[0] == ']') portstr++;
+ if (portstr[0] == ':') portstr++; /* not else if! */
+ cl->ip = eina_stringshare_add_length(addr, p - addr);
+ cl->port = atoi(portstr);
+ }
+ }
+ }
+ else
+ {
+ /* legacy compatibility */
+ cl->ip = eina_stringshare_add("0.0.0.0");
+ cl->port = -1;
+ }
+
+ efl_event_callback_array_add(cl->socket, _ecore_con_client_socket_cbs(), cl);
+ if (efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS))
+ efl_event_callback_array_add(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
+
+ ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+ svr->clients = eina_list_append(svr->clients, cl);
+ return cl;
+}
+
+EAPI int
+ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size)
+{
+ Eina_Error err;
+ Eina_Slice slice = { .mem = data, .len = size };
+
+ ECORE_CON_CLIENT_CHECK_RETURN(cl, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cl->socket, 0);
+ err = efl_io_writer_write(cl->socket, &slice, NULL);
+ if (err)
+ {
+ ERR("cl=%p could not send data=%p, size=%d: %s", cl, data, size, eina_error_msg_get(err));
+ return 0;
+ }
+ cl->pending_write = efl_io_buffered_stream_pending_write_get(cl->socket);
+
+ return slice.len;
+}
+
+EAPI Eina_Bool
+ecore_con_client_connected_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RETURN(cl, EINA_FALSE);
+ return !efl_io_closer_closed_get(cl->socket);
+}
+
+EAPI void
+ecore_con_client_timeout_set(Ecore_Con_Client *cl, double timeout)
+{
+ ECORE_CON_CLIENT_CHECK_RETURN(cl);
+ efl_io_buffered_stream_inactivity_timeout_set(cl->socket, timeout);
+}
+
+EAPI double
+ecore_con_client_timeout_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RETURN(cl, -1.0);
+ return efl_io_buffered_stream_inactivity_timeout_get(cl->socket);
+}
+
+EAPI void *
+ecore_con_client_del(Ecore_Con_Client *cl)
+{
+ const void *data;
+
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
+
+ data = cl->data;
+
+ _ecore_con_client_free(cl);
+ return (void *)data;
+}
+
+EAPI void
+ecore_con_client_data_set(Ecore_Con_Client *cl,
+ const void *data)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl);
+ cl->data = data;
+}
+
+EAPI void *
+ecore_con_client_data_get(Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
+ return (void *)cl->data;
+}
+
+EAPI const char *
+ecore_con_client_ip_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
+ return cl->ip;
+}
+
+EAPI int
+ecore_con_client_port_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, -1);
+ return cl->port;
+}
+
+EAPI Ecore_Con_Server *
+ecore_con_client_server_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
+ return cl->svr;
+}
+
+EAPI double
+ecore_con_client_uptime_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, 0.0);
+ return ecore_time_get() - cl->start_time;
+}
+
+EAPI void
+ecore_con_client_flush(Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RETURN(cl);
+ Eo *inner_socket;
+
+ if (!cl->socket) return;
+
+ efl_io_buffered_stream_flush(cl->socket, EINA_FALSE, EINA_TRUE);
+
+ inner_socket = efl_io_buffered_stream_inner_io_get(cl->socket);
+
+ if (!efl_isa(inner_socket, EFL_NET_SOCKET_TCP_CLASS)) return;
+ if (!efl_net_socket_tcp_cork_get(inner_socket)) return;
+
+ efl_net_socket_tcp_cork_set(inner_socket, EINA_FALSE);
+ efl_net_socket_tcp_cork_set(inner_socket, EINA_TRUE);
+}
+
+EAPI int
+ecore_con_client_fd_get(const Ecore_Con_Client *cl)
+{
+ ECORE_CON_CLIENT_CHECK_RETURN(cl, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
+ if (cl->socket)
+ {
+ if (efl_isa(cl->socket, EFL_LOOP_FD_CLASS))
+ return efl_loop_fd_get(cl->socket);
+ return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
+ }
+ return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
+}
+
+static void
+_ecore_con_client_socket_ssl_ready(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Client *cl = data;
+
+ cl->ssl.upgrading = EINA_FALSE;
+ INF("cl=%p upgraded to SSL at %s", cl, efl_net_socket_address_remote_get(cl->socket));
+ _ecore_con_post_event_client_upgrade(cl);
+}
+
+static void
+_ecore_con_client_socket_ssl_error(void *data, const Efl_Event *event)
+{
+ Ecore_Con_Client *cl = data;
+ Eina_Error *perr = event->info;
+
+ if (cl->delete_me) return;
+
+ WRN("SSL error client %s: %s", efl_net_socket_address_remote_get(cl->socket), eina_error_msg_get(*perr));
+
+ _ecore_con_post_event_client_error(cl, eina_error_msg_get(*perr));
+ _ecore_con_client_socket_close(cl);
+}
+
+EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_client_socket_ssl_cbs,
+ { EFL_NET_SOCKET_SSL_EVENT_SSL_READY, _ecore_con_client_socket_ssl_ready },
+ { EFL_NET_SOCKET_SSL_EVENT_SSL_ERROR, _ecore_con_client_socket_ssl_error });
+
+static void
+_ecore_con_client_ssl_upgrade_job(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Client *cl = data;
+ Eo *loop = ecore_main_loop_get();
+ Eo *inner_socket;
+ Eo *socket;
+ Eo *tcp_socket;
+
+ tcp_socket = cl->socket;
+ cl->socket = NULL; /* take it, will be wrapped */
+
+ inner_socket = efl_add(EFL_NET_SOCKET_SSL_CLASS, loop,
+ efl_net_socket_ssl_adopt(efl_added, tcp_socket, cl->ssl.ctx));
+ EINA_SAFETY_ON_NULL_GOTO(inner_socket, error_inner_socket);
+
+ /* do not reparent tcp_socket! it's owned by server */
+ efl_unref(tcp_socket); /* inner_socket keeps it */
+
+ socket = efl_add(EFL_NET_SOCKET_SIMPLE_CLASS, loop,
+ efl_io_buffered_stream_inner_io_set(efl_added, inner_socket));
+ EINA_SAFETY_ON_NULL_GOTO(socket, error_socket);
+
+ efl_parent_set(inner_socket, socket);
+
+ efl_unref(inner_socket); /* socket keeps it */
+
+ cl->socket = socket;
+ efl_io_closer_close_on_exec_set(socket, EINA_TRUE);
+ efl_io_closer_close_on_destructor_set(socket, EINA_TRUE);
+ efl_event_callback_array_del(tcp_socket, _ecore_con_client_socket_cbs(), cl);
+ efl_event_callback_array_add(socket, _ecore_con_client_socket_cbs(), cl);
+ efl_event_callback_array_add(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
+
+ DBG("socket=%p upgraded to SSL with inner_socket=%p, ssl_ctx=%p, tcp_socket=%p. Start handshake...",
+ cl->socket,
+ efl_io_buffered_stream_inner_io_get(cl->socket),
+ cl->ssl.ctx,
+ tcp_socket);
+ return;
+
+ error_socket:
+ efl_del(inner_socket);
+ error_inner_socket:
+ cl->socket = tcp_socket; /* put it back */
+ _ecore_con_post_event_client_error(cl, "Couldn't finish SSL setup");
+ _ecore_con_post_event_client_del(cl);
+}
+
+static Eo * _ecore_con_server_ssl_ctx_create(const Ecore_Con_Server *svr);
+
+EAPI Eina_Bool
+ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type compl_type)
+{
+ Ecore_Con_Server *svr;
+ Eo *ssl_ctx;
+ double start;
+
+ ECORE_CON_CLIENT_CHECK_RETURN(cl, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL((compl_type & ECORE_CON_SSL) == 0, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->ssl.upgrading, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(efl_io_buffered_stream_inner_io_get(cl->socket), EFL_NET_SOCKET_TCP_CLASS), EINA_FALSE);
+
+ svr = cl->svr;
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_isa(efl_net_server_simple_inner_server_get(svr->server), EFL_NET_SERVER_SSL_CLASS), EINA_FALSE); /* cannot upgrade if already SSL server! */
+
+ start = ecore_time_get();
+ while (efl_io_buffered_stream_pending_write_get(cl->socket) && ((ecore_time_get() - start) <= ecore_animator_frametime_get()))
+ ecore_con_client_flush(cl);
+ if (efl_io_buffered_stream_pending_write_get(cl->socket))
+ {
+ ERR("cl=%p still pending send %zd bytes! Flush client before upgrading to SSL!",
+ cl, efl_io_buffered_stream_pending_write_get(cl->socket));
+ return EINA_FALSE;
+ }
+
+ if ((!svr->ssl.upgrade_type) || (!svr->ssl.clients_ctx))
+ {
+ svr->ssl.upgrade_type = compl_type;
+ svr->ssl.clients_ctx = _ecore_con_server_ssl_ctx_create(svr);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.clients_ctx, EINA_FALSE);
+ }
+
+ if (svr->ssl.upgrade_type == compl_type)
+ ssl_ctx = efl_ref(svr->ssl.clients_ctx);
+ else
+ ssl_ctx = _ecore_con_server_ssl_ctx_create(svr);
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ssl_ctx, EINA_FALSE);
+
+ cl->ssl.upgrading = EINA_TRUE;
+ cl->ssl.ctx = ssl_ctx;
+ efl_future_use(&cl->ssl.job, efl_loop_job(efl_loop_get(cl->socket), cl));
+ efl_future_then(cl->ssl.job, _ecore_con_client_ssl_upgrade_job, NULL, NULL, cl);
+
+ DBG("cl=%p SSL upgrading from %#x to type=%#x", cl, svr->type, compl_type);
+
+ return EINA_TRUE;
+}
+
+/**
+ * @}
+ */
+
+Eina_Bool
+ecore_con_server_check(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ return EINA_TRUE;
+}
+
+static Ecore_Con_Server *
+_ecore_con_server_new(Eina_Bool is_dialer, Ecore_Con_Type type, const char *name, int port, const void *data)
+{
+ Ecore_Con_Server *svr = calloc(1, sizeof(Ecore_Con_Server));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
+ svr->start_time = ecore_time_get();
+ svr->name = eina_stringshare_add(name);
+ svr->port = port;
+ svr->data = data;
+ svr->type = type;
+ svr->is_dialer = is_dialer;
+
+ EINA_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+ _servers = eina_list_append(_servers, svr);
+ return svr;
+}
+
+static void
+_ecore_con_server_dialer_close(Ecore_Con_Server *svr)
+{
+ if (!svr->dialer) return;
+
+ if (!efl_io_closer_closed_get(svr->dialer))
+ efl_io_closer_close(svr->dialer);
+}
+
+static void
+_ecore_con_server_free(Ecore_Con_Server *svr)
+{
+ const char *str;
+
+ svr->delete_me = EINA_TRUE;
+ _servers = eina_list_remove(_servers, svr);
+
+ while (svr->clients)
+ ecore_con_client_del(svr->clients->data);
+
+ _ecore_con_server_dialer_close(svr);
+
+ if (svr->dialer)
+ {
+ efl_del(svr->dialer);
+ svr->dialer = NULL;
+ }
+
+ if (svr->server)
+ {
+ efl_del(svr->server);
+ svr->server = NULL;
+ }
+
+ if (svr->ssl.clients_ctx)
+ {
+ efl_unref(svr->ssl.clients_ctx);
+ svr->ssl.clients_ctx = NULL;
+ }
+
+ if (svr->ssl.job) efl_future_cancel(svr->ssl.job);
+
+ if (svr->event_count) return;
+
+ EINA_LIST_FREE(svr->ssl.certs, str) eina_stringshare_del(str);
+ EINA_LIST_FREE(svr->ssl.privkeys, str) eina_stringshare_del(str);
+ EINA_LIST_FREE(svr->ssl.crls, str) eina_stringshare_del(str);
+ EINA_LIST_FREE(svr->ssl.cafiles, str) eina_stringshare_del(str);
+ eina_stringshare_replace(&svr->ssl.verify_name, NULL);
+
+ svr->data = NULL;
+ eina_stringshare_replace(&svr->name, NULL);
+ eina_stringshare_replace(&svr->ip, NULL);
+
+ EINA_MAGIC_SET(svr, ECORE_MAGIC_NONE);
+ free(svr);
+}
+
+/* BEGIN: post of shared Ecore_Event ***********************************/
+
+static void
+_ecore_con_free_event_server_del(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Del *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ ecore_con_event_server_del_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_del(Ecore_Con_Server *svr)
+{
+ Ecore_Con_Event_Server_Del *ev = ecore_con_event_server_del_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ if (svr->dialer)
+ INF("svr=%p disconnected from %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
+ else if (svr->server)
+ INF("svr=%p stopped serving at %s", svr, efl_net_server_address_get(svr->server));
+ else
+ INF("svr=%p name=%s, port=%d %s destroyed before SSL was configured", svr, svr->name, svr->port, svr->is_dialer ? "dialer" : "server");
+
+ if (svr->connecting)
+ {
+ DBG("svr=%p was still connecting to %s (%s), ignore ECORE_CON_EVENT_SERVER_DEL", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
+ return;
+ }
+
+ ev->server = svr;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, ev, _ecore_con_free_event_server_del, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_server_free(svr);
+}
+
+static void
+_ecore_con_free_event_server_error(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Error *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ free(ev->error);
+ ecore_con_event_server_error_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_error(Ecore_Con_Server *svr, const char *err)
+{
+ Ecore_Con_Event_Server_Error *ev = ecore_con_event_server_error_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ if (svr->dialer)
+ INF("svr=%p error from %s (%s): %s", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer), err);
+ else if (svr->server)
+ INF("svr=%p error at %s: %s", svr, efl_net_server_address_get(svr->server), err);
+ else
+ INF("svr=%p name=%s, port=%d %s error before SSL was configured: %s", svr, svr->name, svr->port, svr->is_dialer ? "dialer" : "server", err);
+
+ ev->server = svr;
+ ev->error = err ? strdup(err) : NULL;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_ERROR, ev, _ecore_con_free_event_server_error, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_server_free(svr);
+}
+
+/* END: post of shared Ecore_Event ***********************************/
+
+
+/* BEGIN: post of Ecore_Event for ecore_con_server_connect() ************/
+
+static void
+_ecore_con_free_event_server_add(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Add *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ ecore_con_event_server_add_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_add(Ecore_Con_Server *svr)
+{
+ Ecore_Con_Event_Server_Add *ev = ecore_con_event_server_add_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->server = svr;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, ev, _ecore_con_free_event_server_add, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_server_free(svr);
+}
+
+static void
+_ecore_con_free_event_server_data(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Data *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ free(ev->data);
+ ecore_con_event_server_data_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_data(Ecore_Con_Server *svr, Eina_Rw_Slice slice)
+{
+ Ecore_Con_Event_Server_Data *ev = ecore_con_event_server_data_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->server = svr;
+ ev->data = slice.mem;
+ ev->size = slice.len;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, ev, _ecore_con_free_event_server_data, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ free(slice.mem);
+}
+
+static void
+_ecore_con_free_event_server_write(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Write *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ ecore_con_event_server_write_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_write(Ecore_Con_Server *svr, size_t size)
+{
+ Ecore_Con_Event_Server_Write *ev = ecore_con_event_server_write_alloc();
+ EINA_SAFETY_ON_NULL_RETURN(ev);
+
+ ev->server = svr;
+ ev->size = size;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_WRITE, ev, _ecore_con_free_event_server_write, NULL);
+ _ecore_con_event_count++;
+}
+
+static void
+_ecore_con_free_event_server_upgrade(void *data EINA_UNUSED, void *event)
+{
+ Ecore_Con_Event_Server_Upgrade *ev = event;
+
+ if (ev->server)
+ {
+ Ecore_Con_Server *svr = ev->server;
+ svr->event_count = eina_list_remove(svr->event_count, ev);
+ if ((!svr->event_count) && (svr->delete_me))
+ _ecore_con_server_free(svr);
+ }
+ ecore_con_event_server_upgrade_free(ev);
+ _ecore_con_event_count--;
+}
+
+static void
+_ecore_con_post_event_server_upgrade(Ecore_Con_Server *svr)
+{
+ Ecore_Con_Event_Server_Upgrade *ev = ecore_con_event_server_upgrade_alloc();
+ EINA_SAFETY_ON_NULL_GOTO(ev, error);
+
+ ev->server = svr;
+ svr->event_count = eina_list_append(svr->event_count, ev);
+
+ ecore_event_add(ECORE_CON_EVENT_SERVER_UPGRADE, ev, _ecore_con_free_event_server_upgrade, NULL);
+ _ecore_con_event_count++;
+ return;
+
+ error:
+ _ecore_con_server_free(svr);
+}
+
+/* END: post of Ecore_Event for ecore_con_server_connect() **************/
+
+static void
+_ecore_con_server_dialer_slice_changed(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eina_Slice ro_slice;
+ Eina_Rw_Slice rw_slice;
+
+ if (svr->delete_me) return;
+ if (svr->ssl.upgrading) return;
+
+ if (!efl_io_buffered_stream_slice_get(svr->dialer, &ro_slice)) return;
+ if (ro_slice.len == 0) return;
+
+ rw_slice = eina_slice_dup(ro_slice);
+ efl_io_buffered_stream_clear(svr->dialer);
+ _ecore_con_post_event_server_data(svr, rw_slice);
+}
+
+static void
+_ecore_con_server_dialer_progress(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ size_t now;
+
+ if (svr->delete_me) return;
+ if (svr->ssl.upgrading) return;
+
+ now = efl_io_buffered_stream_pending_write_get(svr->dialer);
+ if (svr->pending_write == now) return;
+ EINA_SAFETY_ON_TRUE_GOTO(svr->pending_write < now, end); /* forgot to update! */
+
+ _ecore_con_post_event_server_write(svr, svr->pending_write - now);
+
+ end:
+ svr->pending_write = now;
+}
+
+static void
+_ecore_con_server_dialer_finished(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+
+ if (svr->delete_me) return;
+
+ _ecore_con_post_event_server_del(svr);
+}
+
+static void
+_ecore_con_server_dialer_error(void *data, const Efl_Event *event)
+{
+ Ecore_Con_Server *svr = data;
+ Eina_Error *perr = event->info;
+
+ if (svr->delete_me) return;
+
+ WRN("error reaching server %s: %s", efl_net_dialer_address_dial_get(svr->dialer), eina_error_msg_get(*perr));
+
+ _ecore_con_post_event_server_error(svr, eina_error_msg_get(*perr));
+ _ecore_con_server_dialer_close(svr);
+}
+
+static void
+_ecore_con_server_dialer_resolved(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eo *inner_dialer;
+
+ if (svr->delete_me) return;
+
+ inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
+ if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS) ||
+ efl_isa(inner_dialer, EFL_NET_DIALER_UDP_CLASS) ||
+ efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
+ {
+ const char *p, *ip = efl_net_socket_address_remote_get(svr->dialer);
+ EINA_SAFETY_ON_NULL_RETURN(ip);
+
+ if (ip[0] != '[') p = strchr(ip, ':');
+ else
+ {
+ ip++;
+ p = strchr(ip, ']');
+ }
+ EINA_SAFETY_ON_NULL_RETURN(p);
+
+ eina_stringshare_del(svr->ip);
+ svr->ip = eina_stringshare_add_length(ip, p - ip);
+ }
+}
+
+static void
+_ecore_con_server_dialer_connected(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+
+ if (svr->delete_me) return;
+ if (svr->ssl.upgrading)
+ {
+ svr->ssl.upgrading = EINA_FALSE;
+ INF("svr=%p upgraded to SSL at %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
+ _ecore_con_post_event_server_upgrade(svr);
+ return;
+ }
+
+ svr->connecting = EINA_FALSE;
+ svr->start_time = ecore_time_get();
+
+ INF("svr=%p connected to %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
+
+ _ecore_con_post_event_server_add(svr);
+}
+
+EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_server_dialer_cbs,
+ { EFL_IO_BUFFERED_STREAM_EVENT_PROGRESS, _ecore_con_server_dialer_progress },
+ { EFL_IO_BUFFERED_STREAM_EVENT_SLICE_CHANGED, _ecore_con_server_dialer_slice_changed },
+ { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _ecore_con_server_dialer_finished },
+ { EFL_NET_DIALER_EVENT_ERROR, _ecore_con_server_dialer_error },
+ { EFL_NET_DIALER_EVENT_RESOLVED, _ecore_con_server_dialer_resolved },
+ { EFL_NET_DIALER_EVENT_CONNECTED, _ecore_con_server_dialer_connected });
+
+static void
+_ecore_con_server_server_client_add(void *data, const Efl_Event *event)
+{
+ Ecore_Con_Server *svr = data;
+ Ecore_Con_Client *cl;
+ Eo *socket = event->info;
+
+ INF("svr=%p address=%s got client %p (%s) address=%s",
+ svr, efl_net_server_address_get(svr->server),
+ socket,
+ efl_class_name_get(efl_io_buffered_stream_inner_io_get(socket)),
+ efl_net_socket_address_remote_get(socket));
+
+ cl = ecore_con_client_add(svr, socket);
+ EINA_SAFETY_ON_NULL_RETURN(cl);
+
+ _ecore_con_post_event_client_add(cl);
+}
+
+static void
+_ecore_con_server_server_serving(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eo *inner_server;
+ const char *address = efl_net_server_address_get(svr->server);
+ const char *p;
+ char *ip;
+
+ EINA_SAFETY_ON_NULL_RETURN(address);
+
+ INF("svr=%p ready at %s", svr, address);
+
+ if (!svr->want_mcast) return;
+
+ inner_server = efl_net_server_simple_inner_server_get(svr->server);
+
+ if (address[0] != '[') p = strchr(address, ':');
+ else
+ {
+ address++;
+ p = strchr(address, ']');
+ }
+ EINA_SAFETY_ON_NULL_RETURN(p);
+
+ ip = malloc(p - address + 1);
+ EINA_SAFETY_ON_NULL_RETURN(ip);
+
+ memcpy(ip, address, p - address);
+ ip[p - address] = '\0';
+
+ DBG("svr=%p join multicast group: %s", svr, ip);
+ efl_net_server_udp_multicast_join(inner_server, ip);
+ free(ip);
+}
+
+static void
+_ecore_con_server_server_error(void *data, const Efl_Event *event)
+{
+ Ecore_Con_Server *svr = data;
+ Eina_Error *perr = event->info;
+
+ WRN("svr=%p address=%s error: %s",
+ svr, efl_net_server_address_get(svr->server),
+ eina_error_msg_get(*perr));
+
+ _ecore_con_post_event_server_error(svr, eina_error_msg_get(*perr));
+}
+
+EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_server_server_cbs,
+ { EFL_NET_SERVER_EVENT_CLIENT_ADD, _ecore_con_server_server_client_add },
+ { EFL_NET_SERVER_EVENT_SERVING, _ecore_con_server_server_serving },
+ { EFL_NET_SERVER_EVENT_ERROR, _ecore_con_server_server_error });
+
+/**
+ * @addtogroup Ecore_Con_Server_Group Ecore Connection Server Functions
+ *
+ * Functions that operate on Ecore server objects.
+ *
+ * @{
+ */
+
+static Eina_Bool
+_ecore_con_server_server_set(Ecore_Con_Server *svr, Eo *server)
+{
+ char address[4096] = "";
+ Eo *inner_server = efl_net_server_simple_inner_server_get(server);
+ Ecore_Con_Type type = svr->type & ECORE_CON_TYPE;
+ Eina_Error err;
+
+ svr->server = server;
+ efl_event_callback_array_add(server, _ecore_con_server_server_cbs(), svr);
+
+ if (efl_isa(inner_server, EFL_NET_SERVER_TCP_CLASS) ||
+ efl_isa(inner_server, EFL_NET_SERVER_UDP_CLASS) ||
+ efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))
+ {
+ if (strchr(svr->name, ':'))
+ snprintf(address, sizeof(address), "[%s]:%d", svr->name, svr->port);
+ else
+ snprintf(address, sizeof(address), "%s:%d", svr->name, svr->port);
+ }
+ else if (type == ECORE_CON_LOCAL_ABSTRACT)
+ snprintf(address, sizeof(address), "abstract:%s", svr->name);
+ else if ((type == ECORE_CON_LOCAL_USER) ||
+ (type == ECORE_CON_LOCAL_SYSTEM))
+ {
+ char *path = ecore_con_local_path_new(type == ECORE_CON_LOCAL_SYSTEM, svr->name, svr->port);
+ if (!path)
+ {
+ ERR("could not create local path for name='%s', port=%d", svr->name, svr->port);
+ return EINA_FALSE;
+ }
+ else
+ {
+ eina_strlcpy(address, path, sizeof(address));
+ free(path);
+ }
+ }
+
+ if (efl_isa(inner_server, EFL_NET_SERVER_FD_CLASS))
+ {
+ efl_net_server_fd_close_on_exec_set(inner_server, EINA_TRUE);
+ efl_net_server_fd_reuse_address_set(inner_server, EINA_TRUE);
+ efl_net_server_fd_reuse_port_set(inner_server, EINA_TRUE);
+ }
+
+ if (efl_isa(inner_server, EFL_NET_SERVER_TCP_CLASS))
+ {
+ /* old ecore_con did not map ipv4 to ipv6... */
+ efl_net_server_tcp_ipv6_only_set(inner_server, EINA_TRUE);
+ }
+ else if (efl_isa(inner_server, EFL_NET_SERVER_UDP_CLASS))
+ {
+ /* old ecore_con did not map ipv4 to ipv6... */
+ efl_net_server_udp_ipv6_only_set(inner_server, EINA_TRUE);
+ svr->want_mcast = type == ECORE_CON_REMOTE_MCAST;
+ }
+ else if (efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))
+ {
+ /* old ecore_con did not map ipv4 to ipv6... */
+ efl_net_server_ssl_ipv6_only_set(inner_server, EINA_TRUE);
+ efl_net_server_ssl_close_on_exec_set(inner_server, EINA_TRUE);
+ efl_net_server_ssl_reuse_address_set(inner_server, EINA_TRUE);
+ efl_net_server_ssl_reuse_port_set(inner_server, EINA_TRUE);
+ }
+#ifdef EFL_NET_SERVER_UNIX_CLASS
+ else if (efl_isa(inner_server, EFL_NET_SERVER_UNIX_CLASS))
+ {
+ efl_net_server_unix_unlink_before_bind_set(inner_server, EINA_TRUE);
+ efl_net_server_unix_leading_directories_create_set(inner_server, EINA_TRUE, (type == ECORE_CON_LOCAL_SYSTEM) ? 0755 : 0700);
+ }
+#endif
+
+ if (svr->type & ECORE_CON_SOCKET_ACTIVATE)
+ {
+ if (efl_isa(inner_server, EFL_NET_SERVER_FD_CLASS))
+ efl_net_server_fd_socket_activate(inner_server, address);
+ else if (efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))
+ efl_net_server_ssl_socket_activate(inner_server, address);
+ else
+ {
+ ERR("svr=%p (%s): not able to socket-activate this type!", svr, efl_class_name_get(inner_server));
+ goto serve;
+ }
+
+ if (efl_net_server_serving_get(inner_server))
+ {
+ DBG("svr=%p (%s) was socket activated as %s",
+ svr, efl_class_name_get(inner_server), address);
+ return EINA_TRUE;
+ }
+ else
+ ERR("svr=%p (%s): not able to socket-activate as %s. Try to serve...", svr, efl_class_name_get(inner_server), address);
+ }
+
+ serve:
+ err = efl_net_server_serve(svr->server, address);
+ if (err)
+ {
+ WRN("Could not serve at address=%s using class=%s",
+ address, efl_class_name_get(inner_server));
+ return EINA_FALSE;
+ }
+
+ DBG("svr=%p server=%p (%s) address=%s",
+ svr, svr->server, efl_class_name_get(inner_server),
+ efl_net_server_address_get(svr->server));
+ return EINA_TRUE;
+}
+
+static Eo *
+_ecore_con_server_ssl_ctx_create(const Ecore_Con_Server *svr)
+{
+ Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
+ Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
+
+ if (ssl_type & ECORE_CON_USE_MIXED)
+ cipher = EFL_NET_SSL_CIPHER_AUTO;
+ else if (ssl_type & ECORE_CON_USE_TLS)
+ cipher = EFL_NET_SSL_CIPHER_TLSV1;
+ else if (ssl_type & ECORE_CON_USE_SSL3)
+ cipher = EFL_NET_SSL_CIPHER_SSLV3;
+ else if (ssl_type & ECORE_CON_USE_SSL2)
+ {
+ ERR("SSLv2 is unsupported!");
+ return NULL;
+ }
+
+ /* legacy compatibility: server never verified peer, only dialer did */
+
+ return efl_add(EFL_NET_SSL_CONTEXT_CLASS, NULL,
+ efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
+ efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
+ efl_net_ssl_context_certificate_revogation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
+ efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
+ efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
+ efl_net_ssl_context_setup(efl_added, cipher, EINA_FALSE));
+}
+
+static void
+_ecore_con_server_server_ssl_job(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eo *loop = ecore_main_loop_get();
+ Eo *ssl_ctx;
+ Eo *inner_server;
+ Eo *server;
+
+ ssl_ctx = _ecore_con_server_ssl_ctx_create(svr);
+ EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
+
+ inner_server = efl_add(EFL_NET_SERVER_SSL_CLASS, loop,
+ efl_net_server_ssl_context_set(efl_added, ssl_ctx));
+ EINA_SAFETY_ON_NULL_GOTO(inner_server, error_inner_server);
+
+ server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
+ efl_net_server_simple_inner_server_set(efl_added, inner_server));
+ EINA_SAFETY_ON_NULL_GOTO(server, error_server);
+
+ efl_parent_set(inner_server, server);
+
+ efl_unref(ssl_ctx); /* inner_server keeps it */
+ efl_unref(inner_server); /* server keeps it */
+
+ if (!_ecore_con_server_server_set(svr, server))
+ goto error_serve;
+
+ DBG("server=%p configured with inner_server=%p, ssl_ctx=%p",
+ svr->server,
+ efl_net_server_simple_inner_server_get(svr->server),
+ efl_net_server_ssl_context_get(efl_net_server_simple_inner_server_get(svr->server)));
+
+ return;
+
+ error_serve:
+ _ecore_con_post_event_server_error(svr, "Couldn't serve using SSL");
+ _ecore_con_post_event_server_del(svr);
+ return;
+
+ error_server:
+ efl_del(inner_server);
+ error_inner_server:
+ efl_del(ssl_ctx);
+ error_ssl_ctx:
+ _ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup");
+ _ecore_con_post_event_server_del(svr);
+}
+
+/**
+ * @example ecore_con_server_example.c
+ * Shows how to write a simple server using the Ecore_Con library
+ * using ecore_con_server_add()
+ */
+
+EAPI Ecore_Con_Server *
+ecore_con_server_add(Ecore_Con_Type compl_type,
+ const char *name,
+ int port,
+ const void *data)
+{
+ const Efl_Class *cls = NULL;
+ Ecore_Con_Server *svr;
+ Ecore_Con_Type type;
+ Eo *server;
+ Eo *loop;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+ type = compl_type & ECORE_CON_TYPE;
+
+ loop = ecore_main_loop_get();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(loop, NULL);
+
+ svr = _ecore_con_server_new(EINA_FALSE, compl_type, name, port, data);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
+
+ switch (type)
+ {
+ case ECORE_CON_LOCAL_USER:
+ case ECORE_CON_LOCAL_SYSTEM:
+ case ECORE_CON_LOCAL_ABSTRACT:
+#ifdef EFL_NET_SERVER_UNIX_CLASS
+ cls = EFL_NET_SERVER_UNIX_CLASS;
+#else
+ ERR("Your platform doesn't support Efl_Net_Server-compatible local communication");
+ // TODO: maybe write to a file and use TCP
+#endif
+ break;
+
+ case ECORE_CON_REMOTE_TCP:
+ case ECORE_CON_REMOTE_NODELAY:
+ case ECORE_CON_REMOTE_CORK:
+ cls = EFL_NET_SERVER_TCP_CLASS;
+ break;
+
+ case ECORE_CON_REMOTE_UDP:
+ case ECORE_CON_REMOTE_MCAST:
+ cls = EFL_NET_SERVER_UDP_CLASS;
+ break;
+
+ default:
+ ERR("Unsupported type=%#x & %#x = %#x", compl_type, ECORE_CON_TYPE, type);
+ }
+
+ EINA_SAFETY_ON_NULL_GOTO(cls, error);
+
+ if (compl_type & ECORE_CON_SSL)
+ {
+ if (cls != EFL_NET_SERVER_TCP_CLASS)
+ ERR("SSL can only be used with TCP types, got %s, forcing TCP", efl_class_name_get(cls));
+
+ /* efl_net_ssl_context must be created prior to the object as
+ * it's immutable once created. However the previous
+ * Ecore_Con_Server API returned a handle and then configured
+ * it, like in runtime, but in practice it's only effective
+ * before the server starts.
+ *
+ * Then do not create the SSL server right away, instead do it
+ * from a job, let the user configure SSL before the job
+ * finishes.
+ *
+ * EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job) will alert users
+ * trying to configure after the job expires.
+ *
+ * We can do that since the documentation says:
+ *
+ * > Call this function on a server object before main loop
+ * > has started to enable verification of certificates
+ * > against loaded certificates.
+ */
+ svr->ssl.upgrade_type = compl_type;
+ efl_future_use(&svr->ssl.job, efl_loop_job(loop, svr));
+ efl_future_then(svr->ssl.job, _ecore_con_server_server_ssl_job, NULL, NULL, svr);
+ return svr;
+ }
+
+ server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
+ efl_net_server_simple_inner_class_set(efl_added, cls));
+ EINA_SAFETY_ON_NULL_GOTO(server, error);
+
+ if (!_ecore_con_server_server_set(svr, server))
+ goto error;
+
+ return svr;
+
+ error:
+ _ecore_con_server_free(svr);
+ return NULL;
+}
+
+/**
+ * @brief convert @a socks to proxy URL string and apply using efl_net_dialer_proxy_set().
+ *
+ * @param svr the server created by ecore_con_server_connect().
+ * @param socks the socks handle created by
+ * ecore_con_socks4_remote_add() or ecore_con_socks5_remote_add().
+ *
+ * @internal
+ */
+static void
+_ecore_con_server_proxy_apply(Ecore_Con_Server *svr, const Ecore_Con_Socks *socks)
+{
+ char str[4096], port[sizeof(":65536")] = "";
+ const char *protocol;
+ const char *user = "";
+ const char *userpass_sep = "";
+ const char *pass = "";
+ const char *auth_sep = "";
+
+ if (socks->version == 4)
+ {
+ Ecore_Con_Socks_v4 *v4 = (Ecore_Con_Socks_v4 *)socks;
+
+ if (v4->lookup) protocol = "socks4a";
+ else protocol = "socks4";
+
+ if (v4->port > 0)
+ snprintf(port, sizeof(port), ":%d", v4->port);
+
+ if (v4->username)
+ {
+ user = v4->username;
+ auth_sep = "@";
+ }
+ }
+ else if (socks->version == 5)
+ {
+ Ecore_Con_Socks_v5 *v5 = (Ecore_Con_Socks_v5 *)socks;
+
+ if (socks->lookup) protocol = "socks5h";
+ else protocol = "socks5";
+
+ if (v5->port > 0)
+ snprintf(port, sizeof(port), ":%d", v5->port);
+
+ if (v5->username)
+ {
+ user = v5->username;
+ auth_sep = "@";
+
+ if (v5->password)
+ {
+ pass = v5->password;
+ userpass_sep = ":";
+ }
+ }
+ }
+ else
+ {
+ ERR("unsupported socks->version=%d", socks->version);
+ return;
+ }
+
+ snprintf(str, sizeof(str),
+ "%s://%s%s%s%s%s%s",
+ protocol,
+ pass, userpass_sep, user, auth_sep,
+ socks->ip, port);
+ DBG("using proxy url='%s' for server=%s, port=%d",
+ str, svr->name, svr->port);
+
+ efl_net_dialer_proxy_set(svr->dialer, str);
+
+ if (socks->bind)
+ ERR("proxy bind is not supported! Ecore_Con_Socks=%p %s", socks, str);
+}
+
+static Eina_Bool
+_ecore_con_server_dialer_set(Ecore_Con_Server *svr, Eo *dialer)
+{
+ char address[4096] = "";
+ Eo *inner_dialer = efl_io_buffered_stream_inner_io_get(dialer);
+ Ecore_Con_Type type = svr->type & ECORE_CON_TYPE;
+ Eina_Error err;
+
+ svr->dialer = dialer;
+ efl_io_closer_close_on_exec_set(dialer, EINA_TRUE);
+ efl_io_closer_close_on_destructor_set(dialer, EINA_TRUE);
+ efl_io_buffered_stream_inactivity_timeout_set(dialer, svr->timeout);
+ efl_event_callback_array_add(dialer, _ecore_con_server_dialer_cbs(), svr);
+
+ if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS))
+ {
+ efl_net_socket_tcp_no_delay_set(inner_dialer, !!(type & ECORE_CON_REMOTE_NODELAY));
+ efl_net_socket_tcp_cork_set(inner_dialer, !!(type & ECORE_CON_REMOTE_CORK));
+ }
+ else if (efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
+ {
+ efl_net_dialer_ssl_no_delay_set(inner_dialer, !!(type & ECORE_CON_REMOTE_NODELAY));
+ }
+
+ if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS) ||
+ efl_isa(inner_dialer, EFL_NET_DIALER_UDP_CLASS) ||
+ efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
+ {
+ if (strchr(svr->name, ':'))
+ snprintf(address, sizeof(address), "[%s]:%d", svr->name, svr->port);
+ else
+ snprintf(address, sizeof(address), "%s:%d", svr->name, svr->port);
+ }
+ else if (type == ECORE_CON_LOCAL_ABSTRACT)
+ snprintf(address, sizeof(address), "abstract:%s", svr->name);
+ else if ((type == ECORE_CON_LOCAL_USER) ||
+ (type == ECORE_CON_LOCAL_SYSTEM))
+ {
+ char *path = ecore_con_local_path_new(type == ECORE_CON_LOCAL_SYSTEM, svr->name, svr->port);
+ if (!path)
+ {
+ ERR("could not create local path for name='%s', port=%d", svr->name, svr->port);
+ return EINA_FALSE;
+ }
+ else
+ {
+ eina_strlcpy(address, path, sizeof(address));
+ free(path);
+ }
+ }
+
+ if ((svr->type & ECORE_CON_NO_PROXY) == ECORE_CON_NO_PROXY)
+ {
+ DBG("svr=%p not using any proxy for dialer %p (%s)",
+ svr, svr->dialer, efl_class_name_get(inner_dialer));
+ efl_net_dialer_proxy_set(svr->dialer, "");
+ }
+ else if (type > ECORE_CON_LOCAL_ABSTRACT)
+ {
+ if (_ecore_con_proxy_once)
+ {
+ _ecore_con_server_proxy_apply(svr, _ecore_con_proxy_once);
+ _ecore_con_proxy_once = NULL;
+ }
+ else if (_ecore_con_proxy_global)
+ _ecore_con_server_proxy_apply(svr, _ecore_con_proxy_global);
+ }
+
+ svr->connecting = EINA_TRUE;
+
+ err = efl_net_dialer_dial(svr->dialer, address);
+ if (err)
+ {
+ WRN("Could not connect to address=%s using class=%s",
+ address, efl_class_name_get(inner_dialer));
+ return EINA_FALSE;
+ }
+
+ DBG("svr=%p dialer=%p (%s) address=%s",
+ svr, svr->dialer, efl_class_name_get(inner_dialer),
+ efl_net_dialer_address_dial_get(svr->dialer));
+ return EINA_TRUE;
+}
+
+static void
+_ecore_con_server_dialer_ssl_job(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eo *loop = ecore_main_loop_get();
+ Eo *ssl_ctx;
+ Eo *inner_dialer;
+ Eo *dialer;
+ Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
+ Efl_Net_Ssl_Verify_Mode verify_mode = EFL_NET_SSL_VERIFY_MODE_NONE; /* was the default */
+ Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
+
+ if (ssl_type & ECORE_CON_USE_MIXED)
+ cipher = EFL_NET_SSL_CIPHER_AUTO;
+ else if (ssl_type & ECORE_CON_USE_TLS)
+ cipher = EFL_NET_SSL_CIPHER_TLSV1;
+ else if (ssl_type & ECORE_CON_USE_SSL3)
+ cipher = EFL_NET_SSL_CIPHER_SSLV3;
+ else if (ssl_type & ECORE_CON_USE_SSL2)
+ {
+ ERR("SSLv2 is unsupported!");
+ goto error_ssl_ctx;
+ }
+
+ if (svr->ssl.verify)
+ verify_mode = EFL_NET_SSL_VERIFY_MODE_REQUIRED;
+
+ ssl_ctx = efl_add(EFL_NET_SSL_CONTEXT_CLASS, NULL,
+ efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
+ efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
+ efl_net_ssl_context_certificate_revogation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
+ efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
+ efl_net_ssl_context_verify_mode_set(efl_added, verify_mode),
+ efl_net_ssl_context_hostname_set(efl_added, svr->ssl.verify_name ? svr->ssl.verify_name : svr->name),
+ efl_net_ssl_context_hostname_verify_set(efl_added, svr->ssl.verify_basic),
+ efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
+ efl_net_ssl_context_setup(efl_added, cipher, EINA_TRUE));
+ EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
+
+ inner_dialer = efl_add(EFL_NET_DIALER_SSL_CLASS, loop,
+ efl_net_dialer_ssl_context_set(efl_added, ssl_ctx));
+ EINA_SAFETY_ON_NULL_GOTO(inner_dialer, error_inner_dialer);
+
+ dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
+ efl_io_buffered_stream_inner_io_set(efl_added, inner_dialer));
+ EINA_SAFETY_ON_NULL_GOTO(dialer, error_dialer);
+
+ efl_parent_set(inner_dialer, dialer);
+
+ efl_unref(ssl_ctx); /* inner_dialer keeps it */
+ efl_unref(inner_dialer); /* dialer keeps it */
+
+ if (!_ecore_con_server_dialer_set(svr, dialer))
+ goto error_dial;
+
+ DBG("dialer=%p configured with inner_dialer=%p, ssl_ctx=%p",
+ svr->dialer,
+ efl_io_buffered_stream_inner_io_get(svr->dialer),
+ efl_net_dialer_ssl_context_get(efl_io_buffered_stream_inner_io_get(svr->dialer)));
+
+ return;
+
+ error_dial:
+ _ecore_con_post_event_server_error(svr, "Couldn't dial using SSL");
+ _ecore_con_post_event_server_del(svr);
+ return;
+
+ error_dialer:
+ efl_del(inner_dialer);
+ error_inner_dialer:
+ efl_del(ssl_ctx);
+ error_ssl_ctx:
+ _ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup");
+ _ecore_con_post_event_server_del(svr);
+}
+
+static void
+_ecore_con_server_dialer_ssl_upgrade_job(void *data, const Efl_Event *event EINA_UNUSED)
+{
+ Ecore_Con_Server *svr = data;
+ Eo *loop = ecore_main_loop_get();
+ Eo *ssl_ctx;
+ Eo *inner_dialer;
+ Eo *dialer;
+ Eo *tcp_dialer;
+ Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
+ Efl_Net_Ssl_Verify_Mode verify_mode = EFL_NET_SSL_VERIFY_MODE_NONE; /* was the default */
+ Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
+
+ if (ssl_type & ECORE_CON_USE_MIXED)
+ cipher = EFL_NET_SSL_CIPHER_AUTO;
+ else if (ssl_type & ECORE_CON_USE_TLS)
+ cipher = EFL_NET_SSL_CIPHER_TLSV1;
+ else if (ssl_type & ECORE_CON_USE_SSL3)
+ cipher = EFL_NET_SSL_CIPHER_SSLV3;
+ else if (ssl_type & ECORE_CON_USE_SSL2)
+ {
+ ERR("SSLv2 is unsupported!");
+ goto error_ssl_ctx;
+ }
+
+ if (svr->ssl.verify)
+ verify_mode = EFL_NET_SSL_VERIFY_MODE_REQUIRED;
+
+ ssl_ctx = efl_add(EFL_NET_SSL_CONTEXT_CLASS, NULL,
+ efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
+ efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
+ efl_net_ssl_context_certificate_revogation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
+ efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
+ efl_net_ssl_context_verify_mode_set(efl_added, verify_mode),
+ efl_net_ssl_context_hostname_set(efl_added, svr->ssl.verify_name ? svr->ssl.verify_name : svr->name),
+ efl_net_ssl_context_hostname_verify_set(efl_added, svr->ssl.verify_basic),
+ efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
+ efl_net_ssl_context_setup(efl_added, cipher, EINA_TRUE));
+ EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
+
+ tcp_dialer = svr->dialer;
+ svr->dialer = NULL; /* take it, will be wrapped */
+
+ inner_dialer = efl_add(EFL_NET_DIALER_SSL_CLASS, loop,
+ efl_net_socket_ssl_adopt(efl_added, tcp_dialer, ssl_ctx));
+ EINA_SAFETY_ON_NULL_GOTO(inner_dialer, error_inner_dialer);
+
+ efl_parent_set(tcp_dialer, inner_dialer);
+
+ dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
+ efl_io_buffered_stream_inner_io_set(efl_added, inner_dialer));
+ EINA_SAFETY_ON_NULL_GOTO(dialer, error_dialer);
+
+ efl_parent_set(inner_dialer, dialer);
+
+ efl_unref(ssl_ctx); /* inner_dialer keeps it */
+ efl_unref(inner_dialer); /* dialer keeps it */
+
+ svr->dialer = dialer;
+ efl_io_closer_close_on_exec_set(dialer, EINA_TRUE);
+ efl_io_closer_close_on_destructor_set(dialer, EINA_TRUE);
+ efl_event_callback_array_del(tcp_dialer, _ecore_con_server_dialer_cbs(), svr);
+ efl_event_callback_array_add(dialer, _ecore_con_server_dialer_cbs(), svr);
+
+ DBG("dialer=%p upgraded to SSL with inner_dialer=%p, ssl_ctx=%p, tcp_dialer=%p. Start handshake...",
+ svr->dialer,
+ efl_io_buffered_stream_inner_io_get(svr->dialer),
+ efl_net_dialer_ssl_context_get(efl_io_buffered_stream_inner_io_get(svr->dialer)),
+ tcp_dialer);
+ return;
+
+ error_dialer:
+ efl_del(inner_dialer);
+ error_inner_dialer:
+ svr->dialer = tcp_dialer; /* put it back */
+ efl_del(ssl_ctx);
+ error_ssl_ctx:
+ _ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup");
+ _ecore_con_post_event_server_del(svr);
+}
+
+/**
+ * @example ecore_con_client_example.c
+ *
+ * Shows how to write a simple client (dialer that connects to the
+ * example server using ecore_con_server_connect().
+ */
+
+EAPI Ecore_Con_Server *
+ecore_con_server_connect(Ecore_Con_Type compl_type,
+ const char *name,
+ int port,
+ const void *data)
+{
+ const Efl_Class *cls = NULL;
+ Ecore_Con_Server *svr;
+ Ecore_Con_Type type;
+ Eo *dialer;
+ Eo *loop;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+ type = compl_type & ECORE_CON_TYPE;
+
+ loop = ecore_main_loop_get();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(loop, NULL);
+
+ svr = _ecore_con_server_new(EINA_TRUE, compl_type, name, port, data);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
+
+ switch (type)
+ {
+ case ECORE_CON_LOCAL_USER:
+ case ECORE_CON_LOCAL_SYSTEM:
+ case ECORE_CON_LOCAL_ABSTRACT:
+#ifdef EFL_NET_DIALER_UNIX_CLASS
+ cls = EFL_NET_DIALER_UNIX_CLASS;
+#else
+ ERR("Your platform doesn't support Efl_Net_Dialer-compatible local communication");
+ // TODO: maybe write to a file and use TCP
+#endif
+ break;
+
+ case ECORE_CON_REMOTE_TCP:
+ case ECORE_CON_REMOTE_NODELAY:
+ case ECORE_CON_REMOTE_CORK:
+ cls = EFL_NET_DIALER_TCP_CLASS;
+ break;
+
+ case ECORE_CON_REMOTE_UDP:
+ case ECORE_CON_REMOTE_BROADCAST:
+ cls = EFL_NET_DIALER_UDP_CLASS;
+ break;
+
+ default:
+ ERR("Unsupported type=%#x & %#x = %#x", compl_type, ECORE_CON_TYPE, type);
+ }
+ EINA_SAFETY_ON_NULL_GOTO(cls, error);
+
+ if (compl_type & ECORE_CON_SSL)
+ {
+ if (cls != EFL_NET_DIALER_TCP_CLASS)
+ ERR("SSL can only be used with TCP types, got %s, forcing TCP", efl_class_name_get(cls));
+
+ /* efl_net_ssl_context must be created prior to the object as
+ * it's immutable once created. However the previous
+ * Ecore_Con_Server API returned a handle and then configured
+ * it, like in runtime, but in practice it's only effective
+ * before the connection happens.
+ *
+ * Then do not create the SSL dialer right away, instead do it
+ * from a job, let the user configure SSL before the job
+ * finishes.
+ *
+ * EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job) will alert users
+ * trying to configure after the job expires.
+ *
+ * We can do that since the documentation says:
+ *
+ * > Call this function on a server object before main loop
+ * > has started to enable verification of certificates
+ * > against loaded certificates.
+ */
+ efl_future_use(&svr->ssl.job, efl_loop_job(loop, svr));
+ efl_future_then(svr->ssl.job, _ecore_con_server_dialer_ssl_job, NULL, NULL, svr);
+ return svr;
+ }
+
+ dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
+ efl_net_dialer_simple_inner_class_set(efl_added, cls));
+ EINA_SAFETY_ON_NULL_GOTO(dialer, error);
+
+ if (!_ecore_con_server_dialer_set(svr, dialer))
+ goto error;
+
+ return svr;
+
+ error:
+ _ecore_con_server_free(svr);
+ return NULL;
+}
+
+EAPI const char *
+ecore_con_server_name_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
+ return svr->name;
+}
+
+EAPI void
+ecore_con_server_client_limit_set(Ecore_Con_Server *svr,
+ int client_limit,
+ char reject_excess_clients)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+ if (!svr->server) return;
+ efl_net_server_clients_limit_set(svr->server, client_limit, reject_excess_clients);
+}
+
+EAPI const Eina_List *
+ecore_con_server_clients_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, NULL);
+ return svr->clients;
+}
+
+EAPI void
+ecore_con_server_timeout_set(Ecore_Con_Server *svr, double timeout)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+
+ svr->timeout = timeout; /* used for new clients */
+
+ if (!svr->dialer) return;
+ efl_io_buffered_stream_inactivity_timeout_set(svr->dialer, timeout);
+}
+
+EAPI double
+ecore_con_server_timeout_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, -1.0);
+ return svr->timeout;
+}
+
+EAPI void *
+ecore_con_server_del(Ecore_Con_Server *svr)
+{
+ const void *data;
+
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
+
+ data = svr->data;
+
+ _ecore_con_server_free(svr);
+ return (void *)data;
+}
+
+EAPI void *
+ecore_con_server_data_get(Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
+ return (void *)svr->data;
+}
+
+EAPI void *
+ecore_con_server_data_set(Ecore_Con_Server *svr,
+ void *data)
+{
+ const void *old;
+
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
+ old = svr->data;
+ svr->data = data;
+ return (void *)old;
+}
+
+EAPI Eina_Bool
+ecore_con_server_connected_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ if (svr->is_dialer)
+ {
+ if (svr->dialer)
+ return efl_net_dialer_connected_get(svr->dialer);
+ return EINA_FALSE; /* still setting up SSL */
+ }
+ return EINA_TRUE;
+}
+
+EAPI int
+ecore_con_server_port_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, -1);
+ return svr->port;
+}
+
+EAPI int
+ecore_con_server_send(Ecore_Con_Server *svr, const void *data, int size)
+{
+ Eina_Error err;
+ Eina_Slice slice = { .mem = data, .len = size };
+
+ ECORE_CON_SERVER_CHECK_RETURN(svr, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.upgrading, 0);
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->dialer, 0);
+ err = efl_io_writer_write(svr->dialer, &slice, NULL);
+ if (err)
+ {
+ ERR("svr=%p could not send data=%p, size=%d: %s",
+ svr, data, size, eina_error_msg_get(err));
+ return 0;
+ }
+ svr->pending_write = efl_io_buffered_stream_pending_write_get(svr->dialer);
+
+ return slice.len;
+}
+
+EAPI const char *
+ecore_con_server_ip_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
+ return svr->ip;
+}
+
+EAPI double
+ecore_con_server_uptime_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, 0.0);
+ return ecore_time_get() - svr->start_time;
+}
+
+EAPI void
+ecore_con_server_flush(Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+ Eo *inner_dialer;
+
+ if (!svr->dialer) return;
+
+ efl_io_buffered_stream_flush(svr->dialer, EINA_FALSE, EINA_TRUE);
+
+ inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
+
+ if (!efl_isa(inner_dialer, EFL_NET_SOCKET_TCP_CLASS)) return;
+ if (!efl_net_socket_tcp_cork_get(inner_dialer)) return;
+
+ efl_net_socket_tcp_cork_set(inner_dialer, EINA_FALSE);
+ efl_net_socket_tcp_cork_set(inner_dialer, EINA_TRUE);
+}
+
+EAPI int
+ecore_con_server_fd_get(const Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
+ if (svr->dialer)
+ {
+ Eo *inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
+ if (efl_isa(inner_dialer, EFL_LOOP_FD_CLASS))
+ return efl_loop_fd_get(inner_dialer);
+ return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
+ }
+ if (svr->server)
+ {
+ Eo *inner_server = efl_net_server_simple_inner_server_get(svr->server);
+ if (efl_isa(inner_server, EFL_LOOP_FD_CLASS))
+ return efl_loop_fd_get(inner_server);
+ return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
+ }
+ return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
+}
+
+EAPI Eina_Bool
+ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, const char *cert)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cert, EINA_FALSE);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
+
+ svr->ssl.certs = eina_list_append(svr->ssl.certs, eina_stringshare_add(cert));
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, const char *privkey)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(privkey, EINA_FALSE);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
+
+ svr->ssl.privkeys = eina_list_append(svr->ssl.privkeys, eina_stringshare_add(privkey));
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, const char *crl)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(crl, EINA_FALSE);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
+
+ svr->ssl.crls = eina_list_append(svr->ssl.crls, eina_stringshare_add(crl));
+ return EINA_TRUE;
+}
+
EAPI Eina_Bool
-ecore_con_url_url_set(Ecore_Con_Url *obj, const char *url)
+ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, const char *cafile)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cafile, EINA_FALSE);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
+
+ svr->ssl.cafiles = eina_list_append(svr->ssl.cafiles, eina_stringshare_add(cafile));
+ return EINA_TRUE;
+}
+
+EAPI void
+ecore_con_ssl_server_verify(Ecore_Con_Server *svr)
{
- return efl_network_url_set((Ecore_Con_Url *)obj, url);
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
+
+ if (!svr->is_dialer)
+ {
+ /* legacy compatible + print a warning */
+ WRN("svr=%p created with ecore_con_server_add()", svr);
+ return;
+ }
+
+ svr->ssl.verify = EINA_TRUE;
+}
+
+EAPI void
+ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+ EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
+
+ if (!svr->is_dialer)
+ {
+ /* legacy compatible + print a warning */
+ WRN("svr=%p created with ecore_con_server_add()", svr);
+ return;
+ }
+
+ svr->ssl.verify_basic = EINA_TRUE;
+}
+
+EAPI void
+ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *svr, const char *name)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr);
+ EINA_SAFETY_ON_NULL_RETURN(name);
+
+ if (!svr->server) /* SSL adds a job to allow setup */
+ EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
+ else
+ EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
+
+ eina_stringshare_replace(&svr->ssl.verify_name, name);
}
EAPI const char *
-ecore_con_url_url_get(const Ecore_Con_Url *obj)
+ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr)
+{
+ ECORE_CON_SERVER_CHECK_RETURN(svr, NULL);
+ return svr->ssl.verify_name ? svr->ssl.verify_name : svr->name;
+}
+
+EAPI Eina_Bool
+ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type compl_type)
+{
+ double start;
+
+ ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(svr->dialer, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->server != NULL, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.upgrading, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL((compl_type & ECORE_CON_SSL) == 0, EINA_FALSE);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(efl_io_buffered_stream_inner_io_get(svr->dialer), EFL_NET_DIALER_TCP_CLASS), EINA_FALSE);
+
+ start = ecore_time_get();
+ while (efl_io_buffered_stream_pending_write_get(svr->dialer) && ((ecore_time_get() - start) <= ecore_animator_frametime_get()))
+ ecore_con_server_flush(svr);
+ if (efl_io_buffered_stream_pending_write_get(svr->dialer))
+ {
+ ERR("svr=%p still pending send %zd bytes! Flush server before upgrading to SSL!",
+ svr, efl_io_buffered_stream_pending_write_get(svr->dialer));
+ return EINA_FALSE;
+ }
+
+ svr->ssl.upgrading = EINA_TRUE;
+ svr->ssl.upgrade_type = compl_type;
+ efl_future_use(&svr->ssl.job, efl_loop_job(efl_loop_get(svr->dialer), svr));
+ efl_future_then(svr->ssl.job, _ecore_con_server_dialer_ssl_upgrade_job, NULL, NULL, svr);
+
+ DBG("svr=%p SSL upgrading from %#x to type=%#x", svr, svr->type, compl_type);
+
+ return EINA_TRUE;
+}
+
+/**
+ * @}
+ */
+
+static void
+_ecore_con_lookup_done_cb(void *data, const char *host, const char *port EINA_UNUSED, const struct addrinfo *hints EINA_UNUSED, struct addrinfo *result, int gai_error)
{
- return efl_network_url_get((Ecore_Con_Url *)obj);
+ Ecore_Con_Lookup_Ctx *ctx = data;
+
+ ctx->thread = NULL;
+
+ if (gai_error)
+ WRN("Failed to lookup host='%s': %s", host, gai_strerror(gai_error));
+ else if (result)
+ {
+ char ip[INET6_ADDRSTRLEN];
+ const void *mem;
+
+ if (result->ai_family == AF_INET)
+ {
+ const struct sockaddr_in *a = (const struct sockaddr_in *)result->ai_addr;
+ mem = &a->sin_addr;
+ }
+ else if (result->ai_family == AF_INET6)
+ {
+ const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)result->ai_addr;
+ mem = &a->sin6_addr;
+ }
+ else
+ {
+ ERR("unexpected result->ai_family=%d", result->ai_family);
+ goto end;
+ }
+
+ if (!inet_ntop(result->ai_family, mem, ip, sizeof(ip)))
+ {
+ ERR("could not convert IP to string: %s", strerror(errno));
+ goto end;
+ }
+ ctx->cb(result->ai_canonname, ip, result->ai_addr, result->ai_addrlen, (void *)ctx->data);
+ }
+
+ end:
+ freeaddrinfo(result);
+ _ecore_con_lookups = eina_list_remove(_ecore_con_lookups, ctx);
+ free(ctx);
}
+/*
+ * NOTE: this function has numerous problems:
+ * - not able to specify family (IPv4 or IPv6 or both).
+ * - callback reports a single result
+ * - doesn't return a handle to cancel (likely to access memory after free)
+ * - doesn't report errors
+ */
+EAPI Eina_Bool
+ecore_con_lookup(const char *name, Ecore_Con_Dns_Cb done_cb, const void *data)
+{
+ Ecore_Con_Lookup_Ctx *ctx;
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_CANONNAME,
+ };
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, EINA_FALSE);
+
+ ctx = malloc(sizeof(Ecore_Con_Lookup_Ctx));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
+ ctx->cb = done_cb;
+ ctx->data = data;
+
+ ctx->thread = efl_net_ip_resolve_async_new(name, "0", &hints, _ecore_con_lookup_done_cb, ctx);
+ EINA_SAFETY_ON_NULL_GOTO(ctx->thread, error);
+
+ _ecore_con_lookups = eina_list_append(_ecore_con_lookups, ctx);
+ return EINA_TRUE;
+
+ error:
+ free(ctx);
+ return EINA_FALSE;
+}
diff --git a/src/lib/ecore_con/ecore_con_local.c b/src/lib/ecore_con/ecore_con_local.c
index 1cccf046b0..a66a8b4500 100644
--- a/src/lib/ecore_con/ecore_con_local.c
+++ b/src/lib/ecore_con/ecore_con_local.c
@@ -10,8 +10,6 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
#include <pwd.h>
#ifdef HAVE_SYSTEMD
@@ -28,16 +26,8 @@
#include "Ecore_Con.h"
#include "ecore_con_private.h"
-#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + \
- (size_t)(((struct sockaddr_un *)NULL)-> \
- sun_path))
-#define LENGTH_OF_ABSTRACT_SOCKADDR_UN(s, path) (strlen(path) + 1 + \
- (size_t)(((struct sockaddr_un \
- *)NULL)->sun_path))
-
-static int _ecore_con_local_init_count = 0;
-
-static const char *_ecore_con_local_path_get()
+static const char *
+_ecore_con_local_path_get(void)
{
const char *homedir = getenv("XDG_RUNTIME_DIR");
if (!homedir) homedir = eina_environment_home_get();
@@ -46,24 +36,6 @@ static const char *_ecore_con_local_path_get()
return homedir;
}
-int
-ecore_con_local_init(void)
-{
- if (++_ecore_con_local_init_count != 1)
- return _ecore_con_local_init_count;
-
- return _ecore_con_local_init_count;
-}
-
-int
-ecore_con_local_shutdown(void)
-{
- if (--_ecore_con_local_init_count != 0)
- return _ecore_con_local_init_count;
-
- return _ecore_con_local_init_count;
-}
-
EAPI char *
ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port)
{
@@ -125,110 +97,6 @@ ecore_con_local_path_new(Eina_Bool is_system, const char *name, int port)
}
}
-int
-ecore_con_local_connect(Ecore_Con_Server *obj,
- Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler),
- void *data EINA_UNUSED)
-{
-#ifndef HAVE_LOCAL_SOCKETS
- return 0;
-#else
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- char *buf = NULL;
- struct sockaddr_un socket_unix;
- int curstate = 0;
- int socket_unix_len;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
- {
- buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
- }
- else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
- {
- buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
- }
- else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
- {
- buf = strdup(svr->name);
- }
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
-
- svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (svr->fd < 0)
- {
- free(buf);
- return 0;
- }
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
- goto error;
-
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
- goto error;
-
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
- sizeof(curstate)) < 0)
- goto error;
-
- socket_unix.sun_family = AF_UNIX;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
- {
-#ifdef HAVE_ABSTRACT_SOCKETS
- /* copy name insto sun_path, prefixed by null to indicate abstract namespace */
- snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s",
- svr->name);
- socket_unix.sun_path[0] = '\0';
- socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix,
- svr->name);
-#else
- WRN("Your system does not support abstract sockets!");
- goto error;
-#endif
- }
- else
- {
- strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path) - 1);
- socket_unix.sun_path[sizeof(socket_unix.sun_path) - 1] = '\0';
- socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
- }
-
- if (connect(svr->fd, (struct sockaddr *)&socket_unix,
- socket_unix_len) < 0)
- {
- DBG("local connection failed: %s", strerror(errno));
- goto error;
- }
-
- svr->path = buf;
- buf = NULL;
-
- if (svr->type & ECORE_CON_SSL)
- {
- if (!ecore_con_ssl_server_init(obj)) ERR("Can't init SSL");
- }
-
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- cb_done, obj, NULL, NULL);
- if (!svr->fd_handler)
- goto error;
-
- if (!svr->delete_me) ecore_con_event_server_add(obj);
-
- free(buf);
-
- return 1;
-error:
- if (svr->fd) close(svr->fd);
- svr->fd = -1;
- free(buf);
- return 0;
-#endif
-}
-
-#ifdef HAVE_LOCAL_SOCKETS
void
_ecore_con_local_mkpath(const char *path, mode_t mode)
{
@@ -274,168 +142,3 @@ _ecore_con_local_mkpath(const char *path, mode_t mode)
end:
free(s);
}
-#endif
-
-int
-ecore_con_local_listen(
- Ecore_Con_Server *obj,
- Eina_Bool (*
- cb_listen)(void *data,
- Ecore_Fd_Handler *
- fd_handler),
- void *data
- EINA_UNUSED)
-{
-#ifdef HAVE_LOCAL_SOCKETS
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- char *buf = NULL;
- struct sockaddr_un socket_unix;
- struct linger lin;
- mode_t pmode;
- mode_t mask;
- int socket_unix_len;
- Eina_Bool abstract_socket;
-
- mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
-
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
- {
- buf = ecore_con_local_path_new(EINA_FALSE, svr->name, svr->port);
-
- mask = S_IRUSR | S_IWUSR | S_IXUSR;
- _ecore_con_local_mkpath(buf, mask);
-
- mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
- }
- else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
- {
- mask = 0;
- buf = ecore_con_local_path_new(EINA_TRUE, svr->name, svr->port);
- }
- else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
- {
- buf = strdup(svr->name);
- }
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
-
- pmode = umask(mask);
-start:
- socket_unix.sun_family = AF_UNIX;
- if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
- {
- abstract_socket = EINA_TRUE;
-#ifdef HAVE_ABSTRACT_SOCKETS
- /* . is a placeholder */
- snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s",
- svr->name);
- /* first char null indicates abstract namespace */
- socket_unix.sun_path[0] = '\0';
- socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix,
- svr->name);
-#else
- ERR("Your system does not support abstract sockets!");
- goto error_umask;
-#endif
- }
- else
- {
- abstract_socket = EINA_FALSE;
- strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path) - 1);
- socket_unix.sun_path[sizeof(socket_unix.sun_path) - 1] = '\0';
- socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
- }
-
-#ifdef HAVE_SYSTEMD
- if (svr->type & ECORE_CON_SOCKET_ACTIVATE && sd_fd_index < sd_fd_max)
- {
- if (sd_is_socket_unix(SD_LISTEN_FDS_START + sd_fd_index,
- SOCK_STREAM, 1,
- socket_unix.sun_path,
- abstract_socket ? socket_unix_len : 0) <= 0)
- {
- ERR("Your systemd unit seems to provide fd in the wrong order for Socket activation.");
- goto error_umask;
- }
- svr->fd = SD_LISTEN_FDS_START + sd_fd_index++;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
- goto error_umask;
-
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
- sizeof(struct linger)) < 0)
- goto error_umask;
-
- goto fd_ready;
- }
-#else
- (void)abstract_socket;
-#endif
- svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (svr->fd < 0)
- goto error_umask;
-
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
- goto error_fd;
-
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
- goto error_fd;
-
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
- sizeof(struct linger)) < 0)
- goto error_fd;
-
- if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
- {
- DBG("Local socket '%s' bind failed: %s", buf, strerror(errno));
- if ((((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) ||
- ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)) &&
- (connect(svr->fd, (struct sockaddr *)&socket_unix,
- socket_unix_len) < 0))
- {
- DBG("Local socket '%s' connect test failed: %s", buf, strerror(errno));
- if (unlink(buf) >= 0)
- goto start;
- else
- {
- DBG("Local socket '%s' removal failed: %s", buf, strerror(errno));
- goto error_fd;
- }
- }
- }
-
- if (listen(svr->fd, 4096) < 0)
- goto error_fd;
-
-#ifdef HAVE_SYSTEMD
-fd_ready:
-#endif
- svr->path = buf;
- buf = NULL;
-
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- cb_listen, obj, NULL, NULL);
- umask(pmode);
- if (!svr->fd_handler)
- goto error;
-
- free(buf);
-
- return 1;
-
-error_fd:
- close(svr->fd);
- svr->fd = -1;
-error_umask:
- umask(pmode);
-error:
- free(buf);
-#endif /* HAVE_LOCAL_SOCKETS */
- return 0;
-}
-
diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h
index 9db016b003..639fb0d17f 100644
--- a/src/lib/ecore_con/ecore_con_private.h
+++ b/src/lib/ecore_con/ecore_con_private.h
@@ -8,20 +8,14 @@
#define ECORE_MAGIC_CON_CLIENT 0x77556677
#define ECORE_MAGIC_CON_URL 0x77074255
-#define ECORE_CON_TYPE 0x0f
-#define ECORE_CON_SSL 0xf0
-#define ECORE_CON_SUPER_SSL 0xf00
-
-#if HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-#elif HAVE_OPENSSL
-# include <openssl/ssl.h>
-#endif
-
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
#include <inttypes.h>
#define READBUFSIZ 65536
@@ -58,174 +52,8 @@ extern int _ecore_con_log_dom;
#endif
#define CRI(...) EINA_LOG_DOM_CRIT(_ecore_con_log_dom, __VA_ARGS__)
-typedef struct _Ecore_Con_Lookup Ecore_Con_Lookup;
-typedef struct _Ecore_Con_Info Ecore_Con_Info;
typedef struct Ecore_Con_Socks Ecore_Con_Socks_v4;
typedef struct Ecore_Con_Socks_v5 Ecore_Con_Socks_v5;
-typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
-
-typedef enum _Ecore_Con_State
-{
- ECORE_CON_CONNECTED,
- ECORE_CON_DISCONNECTED,
- ECORE_CON_INPROGRESS
-} Ecore_Con_State;
-
-typedef enum _Ecore_Con_Ssl_Error
-{
- ECORE_CON_SSL_ERROR_NONE = 0,
- ECORE_CON_SSL_ERROR_NOT_SUPPORTED,
- ECORE_CON_SSL_ERROR_INIT_FAILED,
- ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED,
- ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED,
- ECORE_CON_SSL_ERROR_SSL3_NOT_SUPPORTED
-} Ecore_Con_Ssl_Error;
-
-typedef enum _Ecore_Con_Ssl_Handshake
-{
- ECORE_CON_SSL_STATE_DONE = 0,
- ECORE_CON_SSL_STATE_HANDSHAKING,
- ECORE_CON_SSL_STATE_INIT
-} Ecore_Con_Ssl_State;
-
-typedef enum Ecore_Con_Proxy_State
-{ /* named PROXY instead of SOCKS in case some handsome and enterprising
- * developer decides to add HTTP CONNECT support
- */
- ECORE_CON_PROXY_STATE_DONE = 0,
- ECORE_CON_PROXY_STATE_RESOLVED,
- ECORE_CON_PROXY_STATE_INIT,
- ECORE_CON_PROXY_STATE_READ,
- ECORE_CON_PROXY_STATE_AUTH,
- ECORE_CON_PROXY_STATE_REQUEST,
- ECORE_CON_PROXY_STATE_CONFIRM,
-} Ecore_Con_Proxy_State;
-
-struct _Efl_Network_Client_Data
-{
-#ifdef _WIN32
- SOCKET fd;
-#else
- int fd;
-#endif
- Ecore_Con_Server *host_server;
- void *data;
- Ecore_Fd_Handler *fd_handler;
- size_t buf_offset;
- Eina_Binbuf *buf;
- const char *ip;
- Eina_List *event_count;
- struct sockaddr *client_addr;
- int client_addr_len;
- double start_time;
- Ecore_Timer *until_deletion;
- double disconnect_time;
-#if HAVE_GNUTLS
- gnutls_datum_t session_ticket;
- gnutls_session_t session;
-#elif HAVE_OPENSSL
- SSL *ssl;
- int ssl_err;
-#endif
- Ecore_Con_Ssl_State ssl_state;
- Eina_Bool handshaking : 1;
- Eina_Bool upgrade : 1; /* STARTTLS queued */
- Eina_Bool delete_me : 1; /* del event has been queued */
-};
-
-typedef struct _Efl_Network_Client_Data Efl_Network_Client_Data;
-
-struct _Efl_Network_Server_Data
-{
-#ifdef _WIN32
- SOCKET fd;
-#else
- int fd;
-#endif
- Ecore_Con_Type type;
- char *name;
- int port;
- char *path;
- void *data;
- Ecore_Fd_Handler *fd_handler;
- Eina_List *clients;
- unsigned int client_count;
- Eina_Binbuf *buf;
- size_t write_buf_offset;
- Eina_List *infos;
- Eina_List *event_count;
- int client_limit;
- pid_t ppid;
- /* socks */
- Ecore_Con_Socks *ecs;
- Ecore_Con_Proxy_State ecs_state;
- int ecs_addrlen;
- unsigned char ecs_addr[16];
- size_t ecs_buf_offset;
- Eina_Binbuf *ecs_buf;
- Eina_Binbuf *ecs_recvbuf;
- const char *proxyip;
- int proxyport;
- /* endsocks */
- const char *verify_name;
-#if HAVE_GNUTLS
- gnutls_session_t session;
- gnutls_anon_client_credentials_t anoncred_c;
- gnutls_anon_server_credentials_t anoncred_s;
- gnutls_psk_client_credentials_t pskcred_c;
- gnutls_psk_server_credentials_t pskcred_s;
- gnutls_certificate_credentials_t cert;
- char *cert_file;
- gnutls_dh_params_t dh_params;
-#elif HAVE_OPENSSL
- SSL_CTX *ssl_ctx;
- SSL *ssl;
- int ssl_err;
-#endif
- double start_time;
- Ecore_Timer *until_deletion;
- double disconnect_time;
- double client_disconnect_time;
- const char *ip;
- Eina_Bool created : 1; /* @c EINA_TRUE if server is our listening server */
- Eina_Bool connecting : 1; /* @c EINA_FALSE if just initialized or connected */
- Eina_Bool handshaking : 1; /* @c EINA_TRUE if server is ssl handshaking */
- Eina_Bool upgrade : 1; /* STARTTLS queued */
- Eina_Bool disable_proxy : 1; /* proxy should never be used with this connection */
- Eina_Bool ssl_prepared : 1;
- Eina_Bool use_cert : 1; /* @c EINA_TRUE if using certificate auth */
- Ecore_Con_Ssl_State ssl_state; /* current state of ssl handshake on the server */
- Eina_Bool verify : 1; /* @c EINA_TRUE if certificates will be verified */
- Eina_Bool verify_basic : 1; /* @c EINA_TRUE if certificates will be verified only against the hostname */
- Eina_Bool reject_excess_clients : 1;
- Eina_Bool delete_me : 1; /* del event has been queued */
-#ifdef _WIN32
- Eina_Bool want_write : 1;
- Eina_Bool read_stop : 1;
- Eina_Bool read_stopped : 1;
- HANDLE pipe;
- HANDLE thread_read;
- HANDLE event_read;
- HANDLE event_peek;
- DWORD nbr_bytes;
-#endif
-};
-
-typedef struct _Efl_Network_Server_Data Efl_Network_Server_Data;
-
-struct _Ecore_Con_Info
-{
- unsigned int size;
- struct addrinfo info;
- char ip[NI_MAXHOST];
- char service[NI_MAXSERV];
-};
-
-struct _Ecore_Con_Lookup
-{
- Ecore_Con_Dns_Cb done_cb;
- const void *data;
-};
struct Ecore_Con_Socks /* v4 */
{
@@ -267,124 +95,18 @@ void ecore_con_libproxy_proxies_free(char **proxies);
char **ecore_con_libproxy_proxies_get(const char *url);
+Eina_Bool ecore_con_server_check(const Ecore_Con_Server *svr);
+
extern Ecore_Con_Socks *_ecore_con_proxy_once;
extern Ecore_Con_Socks *_ecore_con_proxy_global;
void ecore_con_socks_init(void);
void ecore_con_socks_shutdown(void);
-Eina_Bool ecore_con_socks_svr_init(Ecore_Con_Server *svr);
-void ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num);
-void ecore_con_socks_dns_cb(const char *canonname, const char *ip, struct sockaddr *addr, int addrlen, Ecore_Con_Server *svr);
-
-/* from ecore_con.c */
-void ecore_con_server_infos_del(Ecore_Con_Server *svr, void *info);
-void ecore_con_event_proxy_bind(Ecore_Con_Server *svr);
-void ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate);
-void ecore_con_event_server_del(Ecore_Con_Server *svr);
-#define ecore_con_event_server_error(svr, error) _ecore_con_event_server_error((svr), (char*)(error), EINA_TRUE)
-void _ecore_con_event_server_error(Ecore_Con_Server *svr, char *error, Eina_Bool duplicate);
-void ecore_con_event_client_add(Ecore_Con_Client *cl);
-void ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate);
-void ecore_con_event_client_del(Ecore_Con_Client *cl);
-void ecore_con_event_client_error(Ecore_Con_Client *cl, const char *error);
-void _ecore_con_server_kill(Ecore_Con_Server *svr);
-void _ecore_con_client_kill(Ecore_Con_Client *cl);
-
-int ecore_con_local_init(void);
-int ecore_con_local_shutdown(void);
-/* from ecore_local_win32.c */
-#ifdef _WIN32
-Eina_Bool ecore_con_local_listen(Ecore_Con_Server *svr);
-Eina_Bool ecore_con_local_connect(Ecore_Con_Server *svr,
- Eina_Bool (*cb_done)(void *data,
- Ecore_Fd_Handler *fd_handler));
-Eina_Bool ecore_con_local_win32_server_flush(Ecore_Con_Server *svr);
-Eina_Bool ecore_con_local_win32_client_flush(Ecore_Con_Client *cl);
-void ecore_con_local_win32_server_del(Ecore_Con_Server *svr);
-void ecore_con_local_win32_client_del(Ecore_Con_Client *cl);
-#else
-/* from ecore_local.c */
-int ecore_con_local_connect(Ecore_Con_Server *svr,
- Eina_Bool (*cb_done)(
- void *data,
- Ecore_Fd_Handler *fd_handler),
- void *data);
-int ecore_con_local_listen(Ecore_Con_Server *svr,
- Eina_Bool (*cb_listen)(
- void *data,
- Ecore_Fd_Handler *fd_handler),
- void *data);
-#endif
-
-/* from ecore_con_info.c */
-int ecore_con_info_init(void);
-int ecore_con_info_shutdown(void);
-int ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data);
-int ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data);
-int ecore_con_info_udp_connect(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data);
-int ecore_con_info_udp_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data);
-int ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data);
-void ecore_con_info_data_clear(void *info);
-
-void ecore_con_event_server_add(Ecore_Con_Server *svr);
-
-
-/* from ecore_con_ssl.c */
-Ecore_Con_Ssl_Error ecore_con_ssl_init(void);
-Ecore_Con_Ssl_Error ecore_con_ssl_shutdown(void);
-Ecore_Con_Ssl_Error ecore_con_ssl_server_prepare(Ecore_Con_Server *svr, int ssl_type);
-Ecore_Con_Ssl_Error ecore_con_ssl_server_init(Ecore_Con_Server *svr);
-Ecore_Con_Ssl_Error ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr);
-int ecore_con_ssl_server_read(Ecore_Con_Server *svr,
- unsigned char *buf,
- int size);
-int ecore_con_ssl_server_write(Ecore_Con_Server *svr,
- const unsigned char *buf,
- int size);
-Ecore_Con_Ssl_Error ecore_con_ssl_client_init(Ecore_Con_Client *svr);
-Ecore_Con_Ssl_Error ecore_con_ssl_client_shutdown(Ecore_Con_Client *svr);
-int ecore_con_ssl_client_read(Ecore_Con_Client *svr,
- unsigned char *buf,
- int size);
-int ecore_con_ssl_client_write(Ecore_Con_Client *svr,
- const unsigned char *buf,
- int size);
-
-int ecore_con_info_get(Ecore_Con_Server *svr,
- Ecore_Con_Info_Cb done_cb,
- void *data,
- struct addrinfo *hints);
-
-
-#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
- TYPE *Type##_alloc(void); \
- void Type##_free(TYPE *e);
-
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Add, ecore_con_event_client_add);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
-GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Proxy_Bind, ecore_con_event_proxy_bind);
void ecore_con_mempool_init(void);
void ecore_con_mempool_shutdown(void);
-#undef GENERIC_ALLOC_FREE_HEADER
+void ecore_con_legacy_init(void);
+void ecore_con_legacy_shutdown(void);
void _ecore_con_local_mkpath(const char *path, mode_t mode);
@@ -429,6 +151,9 @@ void _ecore_con_local_mkpath(const char *path, mode_t mode);
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0
#endif
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 0
+#endif
/* Windows do not define EAI_SYSTEM, so just define to some number
* that won't be matched, effectively disabling the subsequent
diff --git a/src/lib/ecore_con/ecore_con_socks.c b/src/lib/ecore_con/ecore_con_socks.c
index 0b8425957f..a81d37505f 100644
--- a/src/lib/ecore_con/ecore_con_socks.c
+++ b/src/lib/ecore_con/ecore_con_socks.c
@@ -47,36 +47,6 @@
#include "Ecore_Con.h"
#include "ecore_con_private.h"
-#if defined(_WIN32) && !defined(IF_NAMESIZE)
-#define IF_NAMESIZE 16
-#endif
-
-/* http://tools.ietf.org/html/rfc1928
- o X'00' NO AUTHENTICATION REQUIRED
- o X'01' GSSAPI
- o X'02' USERNAME/PASSWORD
- o X'03' to X'7F' IANA ASSIGNED
- o X'80' to X'FE' RESERVED FOR PRIVATE METHODS
- o X'FF' NO ACCEPTABLE METHODS
- */
-#define ECORE_CON_SOCKS_V5_METHOD_NONE 0
-#define ECORE_CON_SOCKS_V5_METHOD_GSSAPI 1
-#define ECORE_CON_SOCKS_V5_METHOD_USERPASS 2
-
-static int ECORE_CON_SOCKS_V5_METHODS[] =
-{
- ECORE_CON_SOCKS_V5_METHOD_NONE,
-// ECORE_CON_SOCKS_V5_METHOD_GSSAPI, TODO
- ECORE_CON_SOCKS_V5_METHOD_USERPASS
-};
-
-#define ECORE_CON_SOCKS_V5_TOTAL_METHODS (sizeof(ECORE_CON_SOCKS_V5_METHODS) / sizeof(int))
-
-#define _ecore_con_server_kill(svr) do { \
- DBG("KILL %p", (svr)); \
- _ecore_con_server_kill((svr)); \
- } while (0)
-
#define ECORE_CON_SOCKS_VERSION_CHECK(X) do { \
if (!(X) || ((X)->version < 4) || ((X)->version > 5)) \
return; \
@@ -86,15 +56,7 @@ static int ECORE_CON_SOCKS_V5_METHODS[] =
return (ret); \
} while (0)
-#define ECORE_CON_SOCKS_CAST(X) \
- Ecore_Con_Socks_v4 * v4 = NULL; \
- Ecore_Con_Socks_v5 *v5 = NULL; \
- if ((X) && ((X)->version == 4)) \
- v4 = (Ecore_Con_Socks_v4 *)(X); \
- else if ((X) && ((X)->version == 5)) \
- v5 = (Ecore_Con_Socks_v5 *)(X);
-
-Eina_List *ecore_con_socks_proxies = NULL;
+static Eina_List *ecore_con_socks_proxies = NULL;
static Ecore_Con_Socks *
_ecore_con_socks_find(unsigned char version, const char *ip, int port, const char *username, size_t ulen, const char *password, size_t plen)
@@ -133,405 +95,6 @@ _ecore_con_socks_free(Ecore_Con_Socks *ecs)
free(ecs);
}
-static Eina_Bool
-_ecore_con_socks_svr_init_v4(Ecore_Con_Server *obj, Ecore_Con_Socks_v4 *v4)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- size_t addrlen, buflen, ulen = 1;
- unsigned char *sbuf;
-
- addrlen = v4->lookup ? strlen(svr->name) + 1 : 0;
- if (v4->username) ulen += v4->ulen;
- buflen = sizeof(char) * (8 + ulen + addrlen);
- sbuf = malloc(buflen);
- if (!sbuf)
- {
- ecore_con_event_server_error(obj, "Memory allocation failure!");
- _ecore_con_server_kill(obj);
- return EINA_FALSE;
- }
- /* http://en.wikipedia.org/wiki/SOCKS */
- sbuf[0] = 4;
- sbuf[1] = v4->bind ? 2 : 1;
- sbuf[2] = svr->port >> 8;
- sbuf[3] = svr->port & 0xff;
- if (addrlen)
- {
- sbuf[4] = sbuf[5] = sbuf[6] = 0;
- sbuf[7] = 1;
- }
- else
- /* SOCKSv4 only handles IPV4, so addrlen is always 4 */
- memcpy(sbuf + 4, svr->ecs_addr, 4);
- if (v4->username)
- memcpy(sbuf + 8, v4->username, ulen);
- else
- sbuf[8] = 0;
- if (addrlen) memcpy(sbuf + 8 + ulen, svr->name, addrlen);
-
- svr->ecs_buf = eina_binbuf_manage_new(sbuf, buflen, EINA_FALSE);
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_ecore_con_socks_svr_init_v5(Ecore_Con_Server *obj, Ecore_Con_Socks_v5 *v5)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- size_t buflen;
- unsigned int x;
- unsigned char *sbuf;
-
- if (v5->username)
- buflen = sizeof(char) * (2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS);
- else
- buflen = 3;
- sbuf = malloc(buflen);
- if (!sbuf)
- {
- ecore_con_event_server_error(obj, "Memory allocation failure!");
- _ecore_con_server_kill(obj);
- return EINA_FALSE;
- }
- /* http://en.wikipedia.org/wiki/SOCKS
- * http://tools.ietf.org/html/rfc1928
- */
- sbuf[0] = 5;
- if (v5->username)
- {
- sbuf[1] = ECORE_CON_SOCKS_V5_TOTAL_METHODS;
- for (x = 2; x < 2 + ECORE_CON_SOCKS_V5_TOTAL_METHODS; x++)
- sbuf[x] = ECORE_CON_SOCKS_V5_METHODS[x - 2];
- }
- else
- {
- sbuf[1] = 1;
- sbuf[2] = ECORE_CON_SOCKS_V5_METHOD_NONE;
- }
-
- svr->ecs_buf = eina_binbuf_manage_new(sbuf, buflen, EINA_FALSE);
- return EINA_TRUE;
-}
-
-#define ECORE_CON_SOCKS_READ(EXACT) \
- if (num < EXACT) \
- { \
- if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new(); \
- if (!svr->ecs_recvbuf) goto error; \
- eina_binbuf_append_length(svr->ecs_recvbuf, buf, num); \
- /* the slowest connection on earth */ \
- if (eina_binbuf_length_get(svr->ecs_recvbuf) != EXACT) return; \
- data = eina_binbuf_string_get(svr->ecs_recvbuf); \
- } \
- else if (num > EXACT) \
- goto error; \
- else \
- data = buf
-
-static void
-_ecore_con_socks_read_v4(Ecore_Con_Server *obj, Ecore_Con_Socks_v4 *v4 EINA_UNUSED, const unsigned char *buf, unsigned int num)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- const unsigned char *data;
- DBG("SOCKS: %d bytes", num);
- ECORE_CON_SOCKS_READ(8);
-
-/* http://ufasoft.com/doc/socks4_protocol.htm */
- if (data[0]) goto error;
- switch (data[1])
- {
- case 90:
- /* success! */
- break;
-
- case 91:
- ecore_con_event_server_error(obj, "proxy request rejected or failed");
- goto error;
-
- case 92:
- ecore_con_event_server_error(obj, "proxying SOCKS server could not perform authentication");
- goto error;
-
- case 93:
- ecore_con_event_server_error(obj, "proxy request authentication rejected");
- goto error;
-
- default:
- ecore_con_event_server_error(obj, "garbage data from proxy");
- goto error;
- }
- if (svr->ecs->bind)
- {
- unsigned int nport;
- char naddr[IF_NAMESIZE];
-
- memcpy(&nport, &data[2], 2);
- svr->proxyport = ntohl(nport);
-
- if (!inet_ntop(AF_INET, &data[4], naddr, sizeof(naddr))) goto error;
- svr->proxyip = eina_stringshare_add(naddr);
- ecore_con_event_proxy_bind(obj);
- }
- svr->ecs_state = ECORE_CON_PROXY_STATE_DONE;
- INF("PROXY CONNECTED");
- if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
- svr->ecs_recvbuf = NULL;
- svr->ecs_buf_offset = svr->ecs_addrlen = 0;
- memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
- if (!svr->ssl_state)
- ecore_con_event_server_add(obj);
- if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf)))
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
- return;
-error:
- _ecore_con_server_kill(obj);
-}
-
-static Eina_Bool
-_ecore_con_socks_auth_v5(Ecore_Con_Server *obj, Ecore_Con_Socks_v5 *v5)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- size_t size;
- unsigned char *data;
- switch (v5->method)
- {
- case ECORE_CON_SOCKS_V5_METHOD_NONE:
- svr->ecs_state = ECORE_CON_PROXY_STATE_REQUEST;
- return EINA_TRUE;
-
- case ECORE_CON_SOCKS_V5_METHOD_GSSAPI:
- return EINA_TRUE;
-
- case ECORE_CON_SOCKS_V5_METHOD_USERPASS:
- if (!v5->username) return EINA_FALSE;
- if (!v5->password) v5->plen = 1;
- /* http://tools.ietf.org/html/rfc1929 */
- size = sizeof(char) * (3 + v5->ulen + v5->plen);
- data = malloc(size);
- if (!data) break;
- data[0] = 1;
- data[1] = v5->ulen;
- memcpy(&data[2], v5->username, v5->ulen);
- data[1 + v5->ulen] = v5->plen;
- if (v5->password)
- memcpy(&data[2 + v5->ulen], v5->password, v5->plen);
- else
- data[2 + v5->ulen] = 0;
- svr->ecs_buf = eina_binbuf_manage_new(data, size, EINA_FALSE);
- return EINA_TRUE;
-
- default:
- break;
- }
- return EINA_FALSE;
-}
-
-static void
-_ecore_con_socks_read_v5(Ecore_Con_Server *obj, Ecore_Con_Socks_v5 *v5, const unsigned char *buf, unsigned int num)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- const unsigned char *data;
-
- DBG("SOCKS: %d bytes", num);
- switch (svr->ecs_state)
- {
- case ECORE_CON_PROXY_STATE_READ:
- ECORE_CON_SOCKS_READ(2);
- /* http://en.wikipedia.org/wiki/SOCKS */
- if (data[0] != 5) goto error;
- if (data[1] == 0xFF)
- {
- ecore_con_event_server_error(obj, "proxy authentication methods rejected");
- goto error;
- }
- v5->method = data[1];
- if (!_ecore_con_socks_auth_v5(obj, v5)) goto error;
- if (svr->ecs_state == ECORE_CON_PROXY_STATE_REQUEST)
- {
- /* run again to skip auth reading */
- _ecore_con_socks_read_v5(obj, v5, NULL, 0);
- return;
- }
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- svr->ecs_state = ECORE_CON_PROXY_STATE_AUTH;
- break;
-
- case ECORE_CON_PROXY_STATE_AUTH:
- ECORE_CON_SOCKS_READ(2);
- switch (v5->method)
- {
- case ECORE_CON_SOCKS_V5_METHOD_NONE:
- CRI("HOW DID THIS HAPPEN?????????");
- goto error;
-
- case ECORE_CON_SOCKS_V5_METHOD_GSSAPI:
- /* TODO: this */
- break;
-
- case ECORE_CON_SOCKS_V5_METHOD_USERPASS:
- if (data[0] != 1)
- {
- ecore_con_event_server_error(obj, "protocol error");
- goto error; /* wrong version */
- }
- if (data[1])
- {
- ecore_con_event_server_error(obj, "proxy request authentication rejected");
- goto error;
- }
-
- default:
- break;
- }
- break;
-
- case ECORE_CON_PROXY_STATE_REQUEST:
- {
- size_t addrlen, buflen;
- unsigned char *sbuf;
- addrlen = v5->lookup ? strlen(svr->name) + 1 : (unsigned int)svr->ecs_addrlen;
- buflen = sizeof(char) * (6 + addrlen);
- sbuf = malloc(buflen);
- if (!sbuf)
- {
- ecore_con_event_server_error(obj, "Memory allocation failure!");
- goto error;
- }
- sbuf[0] = 5;
- sbuf[1] = v5->bind ? 2 : 1; /* TODO: 0x03 for UDP port association */
- sbuf[2] = 0;
- if (v5->lookup) /* domain name */
- {
- sbuf[3] = 3;
- sbuf[4] = addrlen - 1;
- memcpy(sbuf + 5, svr->name, addrlen - 1);
- }
- else
- {
- sbuf[3] = (svr->ecs_addrlen == 4) ? 1 : 4;
- memcpy(sbuf + 4, svr->ecs_addr, addrlen);
- }
- sbuf[addrlen + 4] = svr->port >> 8;
- sbuf[addrlen + 5] = svr->port & 0xff;
-
- svr->ecs_buf = eina_binbuf_manage_new(sbuf, buflen, EINA_FALSE);
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- break;
- }
-
- case ECORE_CON_PROXY_STATE_CONFIRM:
- {
- /* this is ugly because we have to read an exact number of bytes,
- * but we don't know what that number is until we've already read
- * at least 5 bytes to determine the length of the unknown stream.
- * yep.
- */
- size_t to_read, len = svr->ecs_recvbuf ? eina_binbuf_length_get(svr->ecs_recvbuf) : 0;
- if (num + len < 5)
- {
- /* guarantees we get called again */
- ECORE_CON_SOCKS_READ(5);
- }
- if (len >= 5)
- {
- data = eina_binbuf_string_get(svr->ecs_recvbuf);
- data += 3;
- }
- else
- data = buf + 3 - len;
- switch (data[0])
- {
- case 1:
- to_read = 4;
- break;
-
- case 3:
- to_read = data[1] + 1;
- break;
-
- case 4:
- to_read = 16;
- /* lazy debugging stub comment */
- break;
-
- default:
- ecore_con_event_server_error(obj, "protocol error");
- goto error;
- }
- /* at this point, we finally know exactly how much we need to read */
- ECORE_CON_SOCKS_READ(6 + to_read);
-
- if (data[0] != 5)
- {
- ecore_con_event_server_error(obj, "protocol error");
- goto error; /* wrong version */
- }
- switch (data[1])
- {
- case 0:
- break;
-
- case 1:
- ecore_con_event_server_error(obj, "general proxy failure");
- goto error;
-
- case 2:
- ecore_con_event_server_error(obj, "connection not allowed by ruleset");
- goto error;
-
- case 3:
- ecore_con_event_server_error(obj, "network unreachable");
- goto error;
-
- case 4:
- ecore_con_event_server_error(obj, "host unreachable");
- goto error;
-
- case 5:
- ecore_con_event_server_error(obj, "connection refused by destination host");
- goto error;
-
- case 6:
- ecore_con_event_server_error(obj, "TTL expired");
- goto error;
-
- case 7:
- ecore_con_event_server_error(obj, "command not supported / protocol error");
- goto error;
-
- case 8:
- ecore_con_event_server_error(obj, "address type not supported");
-
- default:
- goto error;
- }
- if (data[2])
- {
- ecore_con_event_server_error(obj, "protocol error");
- goto error;
- }
- memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
- if (!svr->ssl_state)
- ecore_con_event_server_add(obj);
- if (svr->ssl_state || (svr->buf && eina_binbuf_length_get(svr->buf)))
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
- svr->ecs_buf_offset = svr->ecs_addrlen = 0;
- svr->ecs_state = ECORE_CON_PROXY_STATE_DONE;
- INF("PROXY CONNECTED");
- break;
- }
-
- default:
- break;
- }
- if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
- svr->ecs_recvbuf = NULL;
-
- return;
-error:
- _ecore_con_server_kill(obj);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
void
ecore_con_socks_shutdown(void)
{
@@ -543,55 +106,6 @@ ecore_con_socks_shutdown(void)
}
void
-ecore_con_socks_read(Ecore_Con_Server *obj, unsigned char *buf, int num)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- ECORE_CON_SOCKS_VERSION_CHECK(svr->ecs);
- ECORE_CON_SOCKS_CAST(svr->ecs);
-
- if (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) return;
-
- if (v4) _ecore_con_socks_read_v4(obj, v4, buf, (unsigned int)num);
- else _ecore_con_socks_read_v5(obj, v5, buf, (unsigned int)num);
-}
-
-Eina_Bool
-ecore_con_socks_svr_init(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- ECORE_CON_SOCKS_VERSION_CHECK_RETURN(svr->ecs, EINA_FALSE);
- ECORE_CON_SOCKS_CAST(svr->ecs);
-
- if (!svr->ip) return EINA_FALSE;
- if (svr->ecs_buf) return EINA_FALSE;
- if (svr->ecs_state != ECORE_CON_PROXY_STATE_INIT) return EINA_FALSE;
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- if (v4) return _ecore_con_socks_svr_init_v4(obj, v4);
- return _ecore_con_socks_svr_init_v5(obj, v5);
-}
-
-void
-ecore_con_socks_dns_cb(const char *canonname EINA_UNUSED, const char *ip, struct sockaddr *addr, int addrlen EINA_UNUSED, Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- svr->ip = eina_stringshare_add(ip);
- svr->ecs_state++;
- if (addr->sa_family == AF_INET)
- {
- memcpy(svr->ecs_addr, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4);
- svr->ecs_addrlen = 4;
- }
-#ifdef HAVE_IPV6
- else
- {
- memcpy(svr->ecs_addr, &((struct sockaddr_in6 *)addr)->sin6_addr.s6_addr, 16);
- svr->ecs_addrlen = 16;
- }
-#endif
- ecore_con_socks_svr_init(obj);
-}
-
-void
ecore_con_socks_init(void)
{
const char *socks = NULL;
diff --git a/src/lib/ecore_con/ecore_con_ssl.c b/src/lib/ecore_con/ecore_con_ssl.c
deleted file mode 100644
index b6e2c9882e..0000000000
--- a/src/lib/ecore_con/ecore_con_ssl.c
+++ /dev/null
@@ -1,1963 +0,0 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-
-#if HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-# include <gnutls/x509.h>
-# include <gcrypt.h>
-#elif HAVE_OPENSSL
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-# include <openssl/dh.h>
-#endif
-
-#ifdef HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
-#endif
-
-#include <sys/stat.h>
-
-#include <Emile.h>
-
-#include "Ecore.h"
-#include "ecore_con_private.h"
-
-EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0;
-EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0;
-
-static int _init_con_ssl_init_count = 0;
-
-#ifdef HAVE_GNUTLS
-static int _client_connected = 0;
-
-# define SSL_SUFFIX(ssl_func) ssl_func ## _gnutls
-# define _ECORE_CON_SSL_AVAILABLE 1
-
-#elif HAVE_OPENSSL
-
-# define SSL_SUFFIX(ssl_func) ssl_func ## _openssl
-# define _ECORE_CON_SSL_AVAILABLE 2
-
-#else
-# define SSL_SUFFIX(ssl_func) ssl_func ## _none
-# define _ECORE_CON_SSL_AVAILABLE 0
-
-#endif
-
-#if HAVE_GNUTLS
-static void
-_gnutls_print_errors(Eo *conn, int type, int ret)
-{
- char buf[1024];
-
- if (!ret) return;
-
- snprintf(buf, sizeof(buf), "GNUTLS error: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret));
- if (type == ECORE_CON_EVENT_CLIENT_ERROR)
- ecore_con_event_client_error(conn, buf);
- else
- ecore_con_event_server_error(conn, buf);
-}
-
-static void
-_gnutls_print_session(const gnutls_datum_t *cert_list, unsigned int cert_list_size)
-{
- char *c = NULL;
- gnutls_x509_crt_t crt;
- unsigned int x;
-
- if (!eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) return;
- for (x = 0; x < cert_list_size; x++)
- {
- gnutls_x509_crt_init(&crt);
- gnutls_x509_crt_import(crt, &cert_list[x], GNUTLS_X509_FMT_DER);
- gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, (gnutls_datum_t *)&c);
- INF("CERTIFICATE:\n%s", c);
- gnutls_free(c);
- gnutls_x509_crt_deinit(crt);
- crt = NULL;
- }
-}
-
-#ifdef ISCOMFITOR
-static void
-_gnutls_log_func(int level,
- const char *str)
-{
- char buf[128];
- strncpy(buf, str, strlen(str) - 1);
- DBG("|<%d>| %s", level, buf);
-}
-
-#endif
-
-static const char *
-SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status)
-{
- switch (status)
- {
- case GNUTLS_HANDSHAKE_HELLO_REQUEST:
- return "Hello request";
-
- case GNUTLS_HANDSHAKE_CLIENT_HELLO:
- return "Client hello";
-
- case GNUTLS_HANDSHAKE_SERVER_HELLO:
- return "Server hello";
-
- case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:
- return "New session ticket";
-
- case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
- return "Certificate packet";
-
- case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
- return "Server key exchange";
-
- case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
- return "Certificate request";
-
- case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
- return "Server hello done";
-
- case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
- return "Certificate verify";
-
- case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
- return "Client key exchange";
-
- case GNUTLS_HANDSHAKE_FINISHED:
- return "Finished";
-
- case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
- return "Supplemental";
- }
- return NULL;
-}
-
-#elif HAVE_OPENSSL
-
-static void
-_openssl_print_verify_error(int error)
-{
- switch (error)
- {
-#define ERROR_SSL(X) \
-case (X): \
- ERR("%s", #X); \
- break
-#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
- ERROR_SSL(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_GET_CRL
- ERROR_SSL(X509_V_ERR_UNABLE_TO_GET_CRL);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE
- ERROR_SSL(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE
- ERROR_SSL(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY
- ERROR_SSL(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY);
-#endif
-#ifdef X509_V_ERR_CERT_SIGNATURE_FAILURE
- ERROR_SSL(X509_V_ERR_CERT_SIGNATURE_FAILURE);
-#endif
-#ifdef X509_V_ERR_CRL_SIGNATURE_FAILURE
- ERROR_SSL(X509_V_ERR_CRL_SIGNATURE_FAILURE);
-#endif
-#ifdef X509_V_ERR_CERT_NOT_YET_VALID
- ERROR_SSL(X509_V_ERR_CERT_NOT_YET_VALID);
-#endif
-#ifdef X509_V_ERR_CERT_HAS_EXPIRED
- ERROR_SSL(X509_V_ERR_CERT_HAS_EXPIRED);
-#endif
-#ifdef X509_V_ERR_CRL_NOT_YET_VALID
- ERROR_SSL(X509_V_ERR_CRL_NOT_YET_VALID);
-#endif
-#ifdef X509_V_ERR_CRL_HAS_EXPIRED
- ERROR_SSL(X509_V_ERR_CRL_HAS_EXPIRED);
-#endif
-#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
- ERROR_SSL(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD);
-#endif
-#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
- ERROR_SSL(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD);
-#endif
-#ifdef X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD
- ERROR_SSL(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD);
-#endif
-#ifdef X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD
- ERROR_SSL(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
-#endif
-#ifdef X509_V_ERR_OUT_OF_MEM
- ERROR_SSL(X509_V_ERR_OUT_OF_MEM);
-#endif
-#ifdef X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
- ERROR_SSL(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT);
-#endif
-#ifdef X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
- ERROR_SSL(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- ERROR_SSL(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
-#endif
-#ifdef X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
- ERROR_SSL(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE);
-#endif
-#ifdef X509_V_ERR_CERT_CHAIN_TOO_LONG
- ERROR_SSL(X509_V_ERR_CERT_CHAIN_TOO_LONG);
-#endif
-#ifdef X509_V_ERR_CERT_REVOKED
- ERROR_SSL(X509_V_ERR_CERT_REVOKED);
-#endif
-#ifdef X509_V_ERR_INVALID_CA
- ERROR_SSL(X509_V_ERR_INVALID_CA);
-#endif
-#ifdef X509_V_ERR_PATH_LENGTH_EXCEEDED
- ERROR_SSL(X509_V_ERR_PATH_LENGTH_EXCEEDED);
-#endif
-#ifdef X509_V_ERR_INVALID_PURPOSE
- ERROR_SSL(X509_V_ERR_INVALID_PURPOSE);
-#endif
-#ifdef X509_V_ERR_CERT_UNTRUSTED
- ERROR_SSL(X509_V_ERR_CERT_UNTRUSTED);
-#endif
-#ifdef X509_V_ERR_CERT_REJECTED
- ERROR_SSL(X509_V_ERR_CERT_REJECTED);
-#endif
- /* These are 'informational' when looking for issuer cert */
-#ifdef X509_V_ERR_SUBJECT_ISSUER_MISMATCH
- ERROR_SSL(X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
-#endif
-#ifdef X509_V_ERR_AKID_SKID_MISMATCH
- ERROR_SSL(X509_V_ERR_AKID_SKID_MISMATCH);
-#endif
-#ifdef X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH
- ERROR_SSL(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH);
-#endif
-#ifdef X509_V_ERR_KEYUSAGE_NO_CERTSIGN
- ERROR_SSL(X509_V_ERR_KEYUSAGE_NO_CERTSIGN);
-#endif
-
-#ifdef X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
- ERROR_SSL(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER);
-#endif
-#ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
- ERROR_SSL(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION);
-#endif
-#ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN
- ERROR_SSL(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN);
-#endif
-#ifdef X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION
- ERROR_SSL(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
-#endif
-#ifdef X509_V_ERR_INVALID_NON_CA
- ERROR_SSL(X509_V_ERR_INVALID_NON_CA);
-#endif
-#ifdef X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED
- ERROR_SSL(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED);
-#endif
-#ifdef X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE
- ERROR_SSL(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE);
-#endif
-#ifdef X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED
- ERROR_SSL(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED);
-#endif
-
-#ifdef X509_V_ERR_INVALID_EXTENSION
- ERROR_SSL(X509_V_ERR_INVALID_EXTENSION);
-#endif
-#ifdef X509_V_ERR_INVALID_POLICY_EXTENSION
- ERROR_SSL(X509_V_ERR_INVALID_POLICY_EXTENSION);
-#endif
-#ifdef X509_V_ERR_NO_EXPLICIT_POLICY
- ERROR_SSL(X509_V_ERR_NO_EXPLICIT_POLICY);
-#endif
-#ifdef X509_V_ERR_DIFFERENT_CRL_SCOPE
- ERROR_SSL(X509_V_ERR_DIFFERENT_CRL_SCOPE);
-#endif
-#ifdef X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE
- ERROR_SSL(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE);
-#endif
-
-#ifdef X509_V_ERR_UNNESTED_RESOURCE
- ERROR_SSL(X509_V_ERR_UNNESTED_RESOURCE);
-#endif
-
-#ifdef X509_V_ERR_PERMITTED_VIOLATION
- ERROR_SSL(X509_V_ERR_PERMITTED_VIOLATION);
-#endif
-#ifdef X509_V_ERR_EXCLUDED_VIOLATION
- ERROR_SSL(X509_V_ERR_EXCLUDED_VIOLATION);
-#endif
-#ifdef X509_V_ERR_SUBTREE_MINMAX
- ERROR_SSL(X509_V_ERR_SUBTREE_MINMAX);
-#endif
-#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE
- ERROR_SSL(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE);
-#endif
-#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX
- ERROR_SSL(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
-#endif
-#ifdef X509_V_ERR_UNSUPPORTED_NAME_SYNTAX
- ERROR_SSL(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX);
-#endif
-#ifdef X509_V_ERR_CRL_PATH_VALIDATION_ERROR
- ERROR_SSL(X509_V_ERR_CRL_PATH_VALIDATION_ERROR);
-#endif
-
- /* The application is not happy */
-#ifdef X509_V_ERR_APPLICATION_VERIFICATION
- ERROR_SSL(X509_V_ERR_APPLICATION_VERIFICATION);
-#endif
- }
-#undef ERROR_SSL
-}
-
-static void
-_openssl_print_errors(Eo *conn, int type)
-{
- char buf[1024];
- do
- {
- unsigned long err;
-
- err = ERR_get_error();
- if (!err) break;
- snprintf(buf, sizeof(buf), "OpenSSL error: %s", ERR_reason_error_string(err));
- if (type == ECORE_CON_EVENT_CLIENT_ERROR)
- ecore_con_event_client_error(conn, buf);
- else
- ecore_con_event_server_error(conn, buf);
- } while (1);
-}
-
-static Eina_Bool
-_openssl_name_verify(const char *name, const char *svrname)
-{
- if (name[0] == '*')
- {
- /* we allow *.domain.TLD with a wildcard, but nothing else */
- const char *p, *s;
-
- EINA_SAFETY_ON_TRUE_RETURN_VAL((name[1] != '.') || (!name[2]), EINA_FALSE);
- p = strchr(name + 1, '*');
- EINA_SAFETY_ON_TRUE_RETURN_VAL(!!p, EINA_FALSE);
- /* verify that we have a domain of at least *.X.TLD and not *.TLD */
- p = strchr(name + 2, '.');
- EINA_SAFETY_ON_TRUE_RETURN_VAL(!p, EINA_FALSE);
- s = strchr(svrname, '.');
- EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE);
- /* same as above for the stored name */
- EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE);
- if (strcasecmp(s, name + 1))
- {
- ERR("%s != %s", s, name + 1);
- return EINA_FALSE;
- }
- }
- else
- if (strcasecmp(name, svrname))
- {
- ERR("%s != %s", name, svrname);
- return EINA_FALSE;
- }
- return EINA_TRUE;
-}
-
-static void
-_openssl_print_session(SSL *ssl)
-{
- /* print session info into DBG */
- SSL_SESSION *s;
- STACK_OF(X509) * sk;
- BIO *b;
- char log[4096], *p;
- int x;
-
- if (!eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) return;
-
- memset(log, 0, sizeof(log));
- b = BIO_new(BIO_s_mem());
- sk = SSL_get_peer_cert_chain(ssl);
- if (sk)
- {
- DBG("CERTIFICATES:");
- for (x = 0; x < sk_X509_num(sk); x++)
- {
- p = X509_NAME_oneline(X509_get_subject_name(sk_X509_value(sk, x)), log, sizeof(log));
- DBG("%2d s:%s", x, p);
- p = X509_NAME_oneline(X509_get_issuer_name(sk_X509_value(sk, x)), log, sizeof(log));
- DBG(" i:%s", p);
- PEM_write_X509(stderr, sk_X509_value(sk, x));
- }
- }
- s = SSL_get_session(ssl);
- SSL_SESSION_print(b, s);
- fprintf(stderr, "\n");
- while (BIO_read(b, log, sizeof(log)) > 0)
- fprintf(stderr, "%s", log);
-
- BIO_free(b);
-}
-
-#endif
-
-#define SSL_ERROR_CHECK_GOTO_ERROR(X) \
- do \
- { \
- if ((X)) \
- { \
- ERR("Error at %s:%s:%d!", __FILE__, __PRETTY_FUNCTION__, __LINE__); \
- goto error; \
- } \
- } \
- while (0)
-
-static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (Ecore_Con_Server *svr, const char *ca_file);
-static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (Ecore_Con_Server *svr, const char *crl_file);
-static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (Ecore_Con_Server *svr, const char *cert);
-static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (Ecore_Con_Server *svr, const char *key_file);
-
-static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server *svr, int ssl_type);
-static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server *svr);
-static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *svr);
-static int SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server *svr, unsigned char *buf, int size);
-static int SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *svr, const unsigned char *buf, int size);
-
-static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client *cl);
-static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *cl);
-static int SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client *cl,
- unsigned char *buf, int size);
-static int SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client *cl,
- const unsigned char *buf, int size);
-
-/*
- * General SSL API
- */
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_init(void)
-{
- if (!_init_con_ssl_init_count++)
- {
-#if defined ISCOMFITOR && defined HAVE_GNUTLS
- if (eina_log_domain_level_check(_ecore_con_log_dom,
- EINA_LOG_LEVEL_DBG))
- {
- gnutls_global_set_log_level(9);
- gnutls_global_set_log_function(_gnutls_log_func);
- }
-#endif
- emile_init();
-
-#if _ECORE_CON_SSL_AVAILABLE != 0
- ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new();
- ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new();
-#endif
- }
-
- return _init_con_ssl_init_count;
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_shutdown(void)
-{
- /* _init_con_ssl_init_count should not go below zero. */
- if (_init_con_ssl_init_count < 1)
- {
- ERR("ecore_con_ssl_shutdown called without calling ecore_con_ssl_init.\n");
- return 0;
- }
-
- if (!--_init_con_ssl_init_count)
- emile_shutdown();
-
- return _init_con_ssl_init_count;
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_server_prepare(Ecore_Con_Server *svr,
- int ssl_type)
-{
- if (!ssl_type)
- return ECORE_CON_SSL_ERROR_NONE;
- if (!emile_cipher_init())
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-
- // We forcibly disable SSL3 now
- if (ssl_type & ECORE_CON_USE_MIXED)
- ssl_type &= ~ECORE_CON_USE_SSL3;
-
- if (ssl_type & ECORE_CON_USE_SSL2)
- return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
-
- if (ssl_type & ECORE_CON_USE_SSL3)
- return ECORE_CON_SSL_ERROR_SSL3_NOT_SUPPORTED;
-
- return SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr, ssl_type);
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_server_init(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr || !(svr->type & ECORE_CON_SSL))
- return ECORE_CON_SSL_ERROR_NONE;
- return SSL_SUFFIX(_ecore_con_ssl_server_init) (obj);
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_server_shutdown(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr || !(svr->type & ECORE_CON_SSL))
- return ECORE_CON_SSL_ERROR_NONE;
- return SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (obj);
-}
-
-int
-ecore_con_ssl_server_read(Ecore_Con_Server *svr,
- unsigned char *buf,
- int size)
-{
- return SSL_SUFFIX(_ecore_con_ssl_server_read) (svr, buf, size);
-}
-
-int
-ecore_con_ssl_server_write(Ecore_Con_Server *svr,
- const unsigned char *buf,
- int size)
-{
- return SSL_SUFFIX(_ecore_con_ssl_server_write) (svr, buf, size);
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_client_init(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- return ECORE_CON_SSL_ERROR_NONE;
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (!host_server || !(host_server->type & ECORE_CON_SSL))
- return ECORE_CON_SSL_ERROR_NONE;
- return SSL_SUFFIX(_ecore_con_ssl_client_init) (obj);
-}
-
-Ecore_Con_Ssl_Error
-ecore_con_ssl_client_shutdown(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- return ECORE_CON_SSL_ERROR_NONE;
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (!host_server || !(host_server->type & ECORE_CON_SSL))
- return ECORE_CON_SSL_ERROR_NONE;
- return SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (obj);
-}
-
-int
-ecore_con_ssl_client_read(Ecore_Con_Client *cl,
- unsigned char *buf,
- int size)
-{
- return SSL_SUFFIX(_ecore_con_ssl_client_read) (cl, buf, size);
-}
-
-int
-ecore_con_ssl_client_write(Ecore_Con_Client *cl,
- const unsigned char *buf,
- int size)
-{
- return SSL_SUFFIX(_ecore_con_ssl_client_write) (cl, buf, size);
-}
-
-EAPI int
-ecore_con_ssl_available_get(void)
-{
- return _ECORE_CON_SSL_AVAILABLE;
-}
-
-EAPI void
-ecore_con_ssl_server_verify(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return;
-
- svr->verify = EINA_TRUE;
-}
-
-EAPI void
-ecore_con_ssl_server_verify_basic(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return;
-
- svr->verify_basic = EINA_TRUE;
-}
-
-EAPI void
-ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *obj, const char *name)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return;
-
- eina_stringshare_replace(&svr->verify_name, name);
-}
-
-EAPI const char *
-ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return NULL;
-
- return svr->verify_name ? : svr->name;
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_server_cert_add(Ecore_Con_Server *obj,
- const char *cert)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return EINA_FALSE;
-
- if (!svr->ssl_prepared)
- {
- svr->use_cert = EINA_TRUE;
- svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT;
- if (ecore_con_ssl_server_prepare(obj, svr->type & ECORE_CON_SSL))
- return EINA_FALSE;
- }
-
- return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (obj, cert);
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_server_cafile_add(Ecore_Con_Server *obj,
- const char *ca_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return EINA_FALSE;
-
- if (!svr->ssl_prepared)
- {
- svr->use_cert = EINA_TRUE;
- svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT;
- if (ecore_con_ssl_server_prepare(obj, svr->type & ECORE_CON_SSL))
- return EINA_FALSE;
- }
-
- return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (obj, ca_file);
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_server_privkey_add(Ecore_Con_Server *obj,
- const char *key_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return EINA_FALSE;
-
- if (!svr->ssl_prepared)
- {
- svr->use_cert = EINA_TRUE;
- svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT;
- if (ecore_con_ssl_server_prepare(obj, svr->type & ECORE_CON_SSL))
- return EINA_FALSE;
- }
-
- return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (obj, key_file);
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_server_crl_add(Ecore_Con_Server *obj,
- const char *crl_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return EINA_FALSE;
-
- if (!svr->ssl_prepared)
- {
- svr->use_cert = EINA_TRUE;
- svr->type |= ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT;
- if (ecore_con_ssl_server_prepare(obj, svr->type & ECORE_CON_SSL))
- return EINA_FALSE;
- }
-
- return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (obj, crl_file);
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_server_upgrade(Ecore_Con_Server *obj, Ecore_Con_Type ssl_type)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!svr) return EINA_FALSE;
-#if _ECORE_CON_SSL_AVAILABLE == 0
- return EINA_FALSE;
-#endif
-
- if (!svr->ssl_prepared)
- {
- if (ecore_con_ssl_server_prepare(obj, ssl_type))
- return EINA_FALSE;
- }
- if (!svr->use_cert)
- svr->type |= ssl_type;
- svr->upgrade = EINA_TRUE;
- svr->handshaking = EINA_TRUE;
- svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
- return !SSL_SUFFIX(_ecore_con_ssl_server_init) (obj);
-}
-
-EAPI Eina_Bool
-ecore_con_ssl_client_upgrade(Ecore_Con_Client *obj, Ecore_Con_Type ssl_type)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (!cl)
- {
- return EINA_FALSE;
- }
-#if _ECORE_CON_SSL_AVAILABLE == 0
- return EINA_FALSE;
-#endif
-
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- if (!host_server->ssl_prepared)
- {
- if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type))
- return EINA_FALSE;
- }
- if (!host_server->use_cert)
- host_server->type |= ssl_type;
- cl->upgrade = EINA_TRUE;
- host_server->upgrade = EINA_TRUE;
- cl->handshaking = EINA_TRUE;
- cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
- return !SSL_SUFFIX(_ecore_con_ssl_client_init) (obj);
-}
-
-/**
- * @}
- */
-
-#if HAVE_GNUTLS
-
-/*
- * GnuTLS
- */
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *obj,
- int ssl_type)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int ret;
-
- switch (ssl_type)
- {
- case ECORE_CON_USE_TLS:
- case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
- case ECORE_CON_USE_MIXED:
- case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
- break;
-
- default:
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_allocate_credentials(&svr->cert));
-
- if (svr->use_cert)
- {
- if (svr->created)
- {
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_init(&svr->dh_params));
- INF("Generating DH params");
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_generate2(svr->dh_params, 1024));
-
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_server_credentials(&svr->anoncred_s));
- /* TODO: implement PSK */
- // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_server_credentials(&svr->pskcred_s));
-
- gnutls_anon_set_server_dh_params(svr->anoncred_s, svr->dh_params);
- gnutls_certificate_set_dh_params(svr->cert, svr->dh_params);
- //gnutls_psk_set_server_dh_params(svr->pskcred_s, svr->dh_params);
- INF("DH params successfully generated and applied!");
- }
- else
- {
- //SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_client_credentials(&svr->pskcred_c));
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_client_credentials(&svr->anoncred_c));
- }
- }
-
- svr->ssl_prepared = EINA_TRUE;
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- _gnutls_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR, ret);
- _ecore_con_ssl_server_shutdown_gnutls(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- const gnutls_datum_t *cert_list;
- unsigned int iter, cert_list_size;
- gnutls_x509_crt_t cert = NULL;
- const char *priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT";
- int ret = 0;
-
- switch (svr->ssl_state)
- {
- case ECORE_CON_SSL_STATE_DONE:
- return ECORE_CON_SSL_ERROR_NONE;
-
- case ECORE_CON_SSL_STATE_INIT:
- if (svr->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
- return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
-
- switch (svr->type & ECORE_CON_SSL)
- {
- case ECORE_CON_USE_SSL3:
- case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
- priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-TLS1.0:!VERS-TLS1.1:!VERS-TLS1.2";
- break;
-
- case ECORE_CON_USE_TLS:
- case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
- priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-SSL3.0";
- break;
-
- case ECORE_CON_USE_MIXED:
- case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
- break;
-
- default:
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&svr->session, GNUTLS_CLIENT));
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_client(svr->session));
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_server_name_set(svr->session, GNUTLS_NAME_DNS, svr->name, strlen(svr->name)));
- INF("Applying priority string: %s", priority);
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(svr->session, priority, NULL));
- gnutls_handshake_set_private_extensions(svr->session, 1);
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert));
- // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_PSK, svr->pskcred_c));
- if (!svr->use_cert)
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c));
-
- gnutls_dh_set_prime_bits(svr->session, 512);
- gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)((intptr_t)svr->fd));
- svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
-
- case ECORE_CON_SSL_STATE_HANDSHAKING:
- if (!svr->session)
- {
- DBG("Server was previously lost, going to error condition");
- goto error;
- }
- ret = gnutls_handshake(svr->session);
- DBG("calling gnutls_handshake(): returned with '%s'", gnutls_strerror_name(ret));
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));
- if (!ret)
- {
- svr->handshaking = EINA_FALSE;
- svr->ssl_state = ECORE_CON_SSL_STATE_DONE;
- }
- else
- {
- if (gnutls_record_get_direction(svr->session))
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- else
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- default:
- break;
- }
-
- if ((!svr->verify) && (!svr->verify_basic))
- /* not verifying certificates, so we're done! */
- return ECORE_CON_SSL_ERROR_NONE;
- if (svr->verify)
- {
- /* use CRL/CA lists to verify */
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(svr->session, &iter));
- if (iter & GNUTLS_CERT_INVALID)
- ERR("The certificate is not trusted.");
- else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND)
- ERR("The certificate hasn't got a known issuer.");
- else if (iter & GNUTLS_CERT_REVOKED)
- ERR("The certificate has been revoked.");
- else if (iter & GNUTLS_CERT_EXPIRED)
- ERR("The certificate has expired");
- else if (iter & GNUTLS_CERT_NOT_ACTIVATED)
- ERR("The certificate is not yet activated");
-
- if (iter)
- goto error;
- }
- if (gnutls_certificate_type_get(svr->session) != GNUTLS_CRT_X509)
- {
- ERR("Warning: PGP certificates are not yet supported!");
- goto error;
- }
-
- SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(svr->session, &cert_list_size)));
- SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);
-
- _gnutls_print_session(cert_list, cert_list_size);
-
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
-
- SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->verify_name ? : svr->name));
- gnutls_x509_crt_deinit(cert);
- DBG("SSL certificate verification succeeded!");
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- _gnutls_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR, ret);
- if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
- ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(svr->session)));
- if (svr->session && (svr->ssl_state != ECORE_CON_SSL_STATE_DONE))
- {
- ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(svr->session)));
- ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(svr->session)));
- }
- if (cert)
- gnutls_x509_crt_deinit(cert);
- _ecore_con_ssl_server_shutdown_gnutls(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *obj,
- const char *ca_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- struct stat st;
- Eina_Iterator *it;
- const char *file;
- Eina_Bool error = EINA_FALSE;
-
- if (stat(ca_file, &st)) return EINA_FALSE;
- if (S_ISDIR(st.st_mode))
- {
- it = eina_file_ls(ca_file);
- SSL_ERROR_CHECK_GOTO_ERROR(!it);
- EINA_ITERATOR_FOREACH(it, file)
- {
- if (!error)
- {
- if (gnutls_certificate_set_x509_trust_file(svr->cert, file, GNUTLS_X509_FMT_PEM) < 1)
- error++;
- }
- eina_stringshare_del(file);
- }
- eina_iterator_free(it);
- }
- else
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file,
- GNUTLS_X509_FMT_PEM) < 1);
-
- return !error;
-error:
- ERR("Could not load CA file!");
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_crl_add_gnutls(Ecore_Con_Server *obj,
- const char *crl_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_crl_file(svr->cert, crl_file,
- GNUTLS_X509_FMT_PEM) < 1);
-
- return EINA_TRUE;
-error:
- ERR("Could not load CRL file!");
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_privkey_add_gnutls(Ecore_Con_Server *obj,
- const char *key_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_key_file(svr->cert, svr->cert_file, key_file,
- GNUTLS_X509_FMT_PEM));
-
- return EINA_TRUE;
-error:
- ERR("Could not load certificate/key file!");
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cert_add_gnutls(Ecore_Con_Server *obj,
- const char *cert_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (!(svr->cert_file = strdup(cert_file)))
- return EINA_FALSE;
-
- return EINA_TRUE;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (svr->session)
- {
- gnutls_bye(svr->session, GNUTLS_SHUT_RDWR);
- gnutls_deinit(svr->session);
- }
-
- free(svr->cert_file);
- svr->cert_file = NULL;
- if (svr->cert)
- gnutls_certificate_free_credentials(svr->cert);
- svr->cert = NULL;
-
- if ((svr->type & ECORE_CON_SSL) && svr->created)
- {
- if (svr->dh_params)
- {
- gnutls_dh_params_deinit(svr->dh_params);
- svr->dh_params = NULL;
- }
- if (svr->anoncred_s)
- gnutls_anon_free_server_credentials(svr->anoncred_s);
- // if (svr->pskcred_s)
- // gnutls_psk_free_server_credentials(svr->pskcred_s);
-
- svr->anoncred_s = NULL;
- svr->pskcred_s = NULL;
- }
- else if (svr->type & ECORE_CON_SSL)
- {
- if (svr->anoncred_c)
- gnutls_anon_free_client_credentials(svr->anoncred_c);
- // if (svr->pskcred_c)
- // gnutls_psk_free_client_credentials(svr->pskcred_c);
-
- svr->anoncred_c = NULL;
- svr->pskcred_c = NULL;
- }
-
- svr->session = NULL;
-
- return ECORE_CON_SSL_ERROR_NONE;
-}
-
-static int
-_ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *obj,
- unsigned char *buf,
- int size)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int num;
-
- if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
- {
- DBG("Continuing gnutls handshake");
- if (!_ecore_con_ssl_server_init_gnutls(obj))
- return 0;
- return -1;
- }
-
- num = gnutls_record_recv(svr->session, buf, size);
- if (num > 0)
- return num;
-
- if (num == GNUTLS_E_REHANDSHAKE)
- {
- WRN("Rehandshake request ignored");
- return 0;
-
- svr->handshaking = EINA_TRUE;
- svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
- if (!_ecore_con_ssl_server_init_gnutls(obj))
- return 0;
- }
- else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS))
- return 0;
-
- return -1;
-}
-
-static int
-_ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *obj,
- const unsigned char *buf,
- int size)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int num;
-
- if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
- {
- DBG("Continuing gnutls handshake");
- if (!_ecore_con_ssl_server_init_gnutls(obj))
- return 0;
- return -1;
- }
-
- num = gnutls_record_send(svr->session, buf, size);
- if (num > 0)
- return num;
-
- if (num == GNUTLS_E_REHANDSHAKE)
- {
- WRN("Rehandshake request ignored");
- return 0;
-/* this is only partly functional I think? */
- svr->handshaking = EINA_TRUE;
- svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
- if (!_ecore_con_ssl_server_init_gnutls(obj))
- return 0;
- }
- else if (!gnutls_error_is_fatal(num))
- return 0;
-
- return -1;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- const gnutls_datum_t *cert_list;
- unsigned int iter, cert_list_size;
- const char *priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT";
- int ret = 0;
-
- switch (cl->ssl_state)
- {
- case ECORE_CON_SSL_STATE_DONE:
- return ECORE_CON_SSL_ERROR_NONE;
-
- case ECORE_CON_SSL_STATE_INIT:
- if (host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
- return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
-
- switch (host_server->type & ECORE_CON_SSL)
- {
- case ECORE_CON_USE_SSL3:
- case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
- priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-TLS1.0:!VERS-TLS1.1:!VERS-TLS1.2";
- break;
-
- case ECORE_CON_USE_TLS:
- case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
- priority = "NORMAL:%VERIFY_ALLOW_X509_V1_CA_CRT:!VERS-SSL3.0";
- break;
-
- case ECORE_CON_USE_MIXED:
- case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
- break;
-
- default:
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- _client_connected++;
-
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER));
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket));
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket));
- INF("Applying priority string: %s", priority);
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL));
- gnutls_handshake_set_private_extensions(cl->session, 1);
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, host_server->cert));
- // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, host_server->pskcred_s));
- if (!host_server->use_cert)
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, host_server->anoncred_s));
-
- gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST);
-
- gnutls_dh_set_prime_bits(cl->session, 2048);
- gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd));
- cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
-
- case ECORE_CON_SSL_STATE_HANDSHAKING:
- if (!cl->session)
- {
- DBG("Client was previously lost, going to error condition");
- goto error;
- }
- DBG("calling gnutls_handshake()");
- ret = gnutls_handshake(cl->session);
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));
-
- if (!ret)
- {
- cl->handshaking = EINA_FALSE;
- cl->ssl_state = ECORE_CON_SSL_STATE_DONE;
- }
- else
- {
- if (gnutls_record_get_direction(cl->session))
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
- else
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- default:
- break;
- }
-
- if (!host_server->verify)
- /* not verifying certificates, so we're done! */
- return ECORE_CON_SSL_ERROR_NONE;
- /* use CRL/CA lists to verify */
- SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter));
- if (iter & GNUTLS_CERT_INVALID)
- ERR("The certificate is not trusted.");
- else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND)
- ERR("The certificate hasn't got a known issuer.");
- else if (iter & GNUTLS_CERT_REVOKED)
- ERR("The certificate has been revoked.");
- else if (iter & GNUTLS_CERT_EXPIRED)
- ERR("The certificate has expired");
- else if (iter & GNUTLS_CERT_NOT_ACTIVATED)
- ERR("The certificate is not yet activated");
-
- if (iter)
- goto error;
- if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509)
- {
- ERR("Warning: PGP certificates are not yet supported!");
- goto error;
- }
-
- SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size)));
- SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);
-
- _gnutls_print_session(cert_list, cert_list_size);
-/*
- gnutls_x509_crt_t cert = NULL;
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
- SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
-
- SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, host_server->name));
- gnutls_x509_crt_deinit(cert);
- */
- DBG("SSL certificate verification succeeded!");
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- _gnutls_print_errors(obj, ECORE_CON_EVENT_CLIENT_ERROR, ret);
- if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
- ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session)));
- if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE))
- {
- ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session)));
- ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session)));
- }
-/*
- if (cert)
- gnutls_x509_crt_deinit(cert);
- */
- _ecore_con_ssl_client_shutdown_gnutls(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (cl->session)
- {
- gnutls_bye(cl->session, GNUTLS_SHUT_RDWR);
- gnutls_deinit(cl->session);
- gnutls_free(cl->session_ticket.data);
- cl->session_ticket.data = NULL;
- }
-
- cl->session = NULL;
-
- return ECORE_CON_SSL_ERROR_NONE;
-}
-
-static int
-_ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *obj,
- unsigned char *buf,
- int size)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int num;
-
- if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
- {
- if (!_ecore_con_ssl_client_init_gnutls(obj))
- return 0;
- return -1;
- }
-
- num = gnutls_record_recv(cl->session, buf, size);
- if (num > 0)
- return num;
-
- if (num == GNUTLS_E_REHANDSHAKE)
- {
- WRN("Rehandshake request ignored");
- return 0;
- cl->handshaking = EINA_TRUE;
- cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
- if (!_ecore_con_ssl_client_init_gnutls(obj))
- return 0;
- WRN("Rehandshake request ignored");
- return 0;
- }
- else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS))
- return 0;
-
- return -1;
-}
-
-static int
-_ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *obj,
- const unsigned char *buf,
- int size)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int num;
-
- if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
- {
- if (!_ecore_con_ssl_client_init_gnutls(obj))
- return 0;
- return -1;
- }
-
- num = gnutls_record_send(cl->session, buf, size);
- if (num > 0)
- return num;
-
- if (num == GNUTLS_E_REHANDSHAKE)
- {
- WRN("Rehandshake request ignored");
- return 0;
- cl->handshaking = EINA_TRUE;
- cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
- if (!_ecore_con_ssl_client_init_gnutls(obj))
- return 0;
- }
- else if (!gnutls_error_is_fatal(num))
- return 0;
-
- return -1;
-}
-
-#elif HAVE_OPENSSL && !HAVE_GNUTLS
-
-/*
- * OpenSSL
- */
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *obj,
- int ssl_type)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- long options;
- int dh = 0;
-
- switch (ssl_type)
- {
- case ECORE_CON_USE_TLS:
- case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
- if (!svr->created)
- SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())));
- else
- SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method())));
- break;
-
- case ECORE_CON_USE_MIXED:
- case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
- if (!svr->created)
- SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method())));
- else
- SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method())));
- options = SSL_CTX_get_options(svr->ssl_ctx);
- SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
- break;
-
- default:
- svr->ssl_prepared = EINA_TRUE;
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- if ((!svr->use_cert) && svr->created)
- {
- DH *dh_params;
- INF("Generating DH params");
- SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new()));
- SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL));
- SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh));
- SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME));
- SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params));
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params));
- DH_free(dh_params);
- INF("DH params successfully generated and applied!");
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aRSA+HIGH:+kEDH:+kRSA:!kSRP:!kPSK:+3DES:!MD5"));
- }
- else if (!svr->use_cert)
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aRSA+HIGH:+kEDH:+kRSA:!kSRP:!kPSK:+3DES:!MD5"));
-
- svr->ssl_prepared = EINA_TRUE;
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- if (dh)
- {
- if (dh & DH_CHECK_P_NOT_PRIME)
- ERR("openssl error: dh_params could not generate a prime!");
- else
- ERR("openssl error: dh_params could not generate a safe prime!");
- }
- else
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- _ecore_con_ssl_server_shutdown_openssl(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_init_openssl(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int ret = -1;
-
- switch (svr->ssl_state)
- {
- case ECORE_CON_SSL_STATE_DONE:
- return ECORE_CON_SSL_ERROR_NONE;
-
- case ECORE_CON_SSL_STATE_INIT:
- SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx)));
-
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd));
- SSL_set_connect_state(svr->ssl);
- svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
-
- case ECORE_CON_SSL_STATE_HANDSHAKING:
- if (!svr->ssl)
- {
- DBG("Server was previously lost, going to error condition");
- goto error;
- }
- ret = SSL_do_handshake(svr->ssl);
- svr->ssl_err = SSL_get_error(svr->ssl, ret);
- SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL));
-
- if (ret == 1)
- {
- svr->handshaking = EINA_FALSE;
- svr->ssl_state = ECORE_CON_SSL_STATE_DONE;
- }
- else
- {
- if (svr->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- else if (svr->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- default:
- break;
- }
-
- _openssl_print_session(svr->ssl);
- if ((!svr->verify) && (!svr->verify_basic))
- /* not verifying certificates, so we're done! */
- return ECORE_CON_SSL_ERROR_NONE;
-
- {
- X509 *cert;
- SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL);
- /* use CRL/CA lists to verify */
- cert = SSL_get_peer_certificate(svr->ssl);
- if (cert)
- {
- char *c;
- int clen;
- int name = 0;
-
- if (svr->verify)
- {
- int err;
-
- err = SSL_get_verify_result(svr->ssl);
- _openssl_print_verify_error(err);
- SSL_ERROR_CHECK_GOTO_ERROR(err);
- }
- clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, NULL, 0);
- if (clen > 0)
- name = NID_subject_alt_name;
- else
- clen = X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, NULL, 0);
- SSL_ERROR_CHECK_GOTO_ERROR(clen < 1);
- if (!name) name = NID_commonName;
- c = alloca(++clen);
- X509_NAME_get_text_by_NID(X509_get_subject_name(cert), name, c, clen);
- INF("CERT NAME: %s\n", c);
- SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(c, svr->verify_name ? : svr->name));
- }
- }
-
- DBG("SSL certificate verification succeeded!");
-
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- _ecore_con_ssl_server_shutdown_openssl(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *obj,
- const char *ca_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- struct stat st;
-
- if (stat(ca_file, &st)) return EINA_FALSE;
- if (S_ISDIR(st.st_mode))
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, NULL, ca_file));
- else
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL));
- return EINA_TRUE;
-
-error:
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_crl_add_openssl(Ecore_Con_Server *obj,
- const char *crl_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- X509_STORE *st;
- X509_LOOKUP *lu;
- static Eina_Bool flag = EINA_FALSE;
-
- SSL_ERROR_CHECK_GOTO_ERROR(!(st = SSL_CTX_get_cert_store(svr->ssl_ctx)));
- SSL_ERROR_CHECK_GOTO_ERROR(!(lu = X509_STORE_add_lookup(st, X509_LOOKUP_file())));
- SSL_ERROR_CHECK_GOTO_ERROR(X509_load_crl_file(lu, crl_file, X509_FILETYPE_PEM) < 1);
- if (!flag)
- {
- X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
- flag = EINA_TRUE;
- }
-
- return EINA_TRUE;
-
-error:
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_privkey_add_openssl(Ecore_Con_Server *obj,
- const char *key_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- FILE *fp = NULL;
- EVP_PKEY *privkey = NULL;
-
- if (!(fp = fopen(key_file, "rb")))
- goto error;
-
- SSL_ERROR_CHECK_GOTO_ERROR(!(privkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)));
-
- fclose(fp);
- fp = NULL;
- SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_PrivateKey(svr->ssl_ctx, privkey) < 1);
- SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_check_private_key(svr->ssl_ctx) < 1);
-
- return EINA_TRUE;
-
-error:
- if (fp)
- fclose(fp);
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cert_add_openssl(Ecore_Con_Server *obj,
- const char *cert_file)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- FILE *fp = NULL;
- X509 *cert = NULL;
-
- if (!(fp = fopen(cert_file, "rb")))
- goto error;
-
- SSL_ERROR_CHECK_GOTO_ERROR(!(cert = PEM_read_X509(fp, NULL, NULL, NULL)));
-
- fclose(fp);
- fp = NULL;
- SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_certificate(svr->ssl_ctx, cert) < 1);
-
- return EINA_TRUE;
-
-error:
- if (fp)
- fclose(fp);
- _openssl_print_errors(obj, ECORE_CON_EVENT_SERVER_ERROR);
- return EINA_FALSE;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *obj)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- if (svr->ssl)
- {
- if (!SSL_shutdown(svr->ssl))
- SSL_shutdown(svr->ssl);
-
- SSL_free(svr->ssl);
- }
-
- if (svr->ssl_ctx)
- SSL_CTX_free(svr->ssl_ctx);
-
- svr->ssl = NULL;
- svr->ssl_ctx = NULL;
- svr->ssl_err = SSL_ERROR_NONE;
-
- return ECORE_CON_SSL_ERROR_NONE;
-}
-
-static int
-_ecore_con_ssl_server_read_openssl(Ecore_Con_Server *obj,
- unsigned char *buf,
- int size)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int num;
-
- if (!svr->ssl) return -1;
- num = SSL_read(svr->ssl, buf, size);
- svr->ssl_err = SSL_get_error(svr->ssl, num);
-
- if (svr->fd_handler)
- {
- if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- }
-
- if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
- (svr->ssl_err == SSL_ERROR_SYSCALL) ||
- (svr->ssl_err == SSL_ERROR_SSL))
- return -1;
-
- if (num < 0)
- return 0;
-
- return num;
-}
-
-static int
-_ecore_con_ssl_server_write_openssl(Ecore_Con_Server *obj,
- const unsigned char *buf,
- int size)
-{
- Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
- int num;
-
- num = SSL_write(svr->ssl, buf, size);
- svr->ssl_err = SSL_get_error(svr->ssl, num);
-
- if (svr->fd_handler)
- {
- if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
- else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
- }
-
- if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
- (svr->ssl_err == SSL_ERROR_SYSCALL) ||
- (svr->ssl_err == SSL_ERROR_SSL))
- return -1;
-
- if (num < 0)
- return 0;
-
- return num;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_init_openssl(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
- int ret = -1;
- switch (cl->ssl_state)
- {
- case ECORE_CON_SSL_STATE_DONE:
- return ECORE_CON_SSL_ERROR_NONE;
-
- case ECORE_CON_SSL_STATE_INIT:
- SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(host_server->ssl_ctx)));
-
- SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd));
- SSL_set_accept_state(cl->ssl);
- cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
-
- case ECORE_CON_SSL_STATE_HANDSHAKING:
- if (!cl->ssl)
- {
- DBG("Client was previously lost, going to error condition");
- goto error;
- }
- ret = SSL_do_handshake(cl->ssl);
- cl->ssl_err = SSL_get_error(cl->ssl, ret);
- SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL));
- if (ret == 1)
- {
- cl->handshaking = EINA_FALSE;
- cl->ssl_state = ECORE_CON_SSL_STATE_DONE;
- }
- else
- {
- if (cl->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- else if (cl->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
- return ECORE_CON_SSL_ERROR_NONE;
- }
-
- default:
- break;
- }
-
- _openssl_print_session(cl->ssl);
- if (!host_server->verify)
- /* not verifying certificates, so we're done! */
- return ECORE_CON_SSL_ERROR_NONE;
- SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL);
- /* use CRL/CA lists to verify */
- if (SSL_get_peer_certificate(cl->ssl))
- {
- int err;
-
- err = SSL_get_verify_result(cl->ssl);
- _openssl_print_verify_error(err);
- SSL_ERROR_CHECK_GOTO_ERROR(err);
- }
-
- return ECORE_CON_SSL_ERROR_NONE;
-
-error:
- _openssl_print_errors(obj, ECORE_CON_EVENT_CLIENT_ERROR);
- _ecore_con_ssl_client_shutdown_openssl(obj);
- return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *obj)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- if (cl->ssl)
- {
- if (!SSL_shutdown(cl->ssl))
- SSL_shutdown(cl->ssl);
-
- SSL_free(cl->ssl);
- }
-
- cl->ssl = NULL;
- cl->ssl_err = SSL_ERROR_NONE;
-
- return ECORE_CON_SSL_ERROR_NONE;
-}
-
-static int
-_ecore_con_ssl_client_read_openssl(Ecore_Con_Client *obj,
- unsigned char *buf,
- int size)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int num;
-
- if (!cl->ssl) return -1;
- num = SSL_read(cl->ssl, buf, size);
- cl->ssl_err = SSL_get_error(cl->ssl, num);
-
- if (cl->fd_handler)
- {
- if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
- }
-
- if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
- (cl->ssl_err == SSL_ERROR_SYSCALL) ||
- (cl->ssl_err == SSL_ERROR_SSL))
- return -1;
-
- if (num < 0)
- return 0;
-
- return num;
-}
-
-static int
-_ecore_con_ssl_client_write_openssl(Ecore_Con_Client *obj,
- const unsigned char *buf,
- int size)
-{
- Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
- int num;
-
- num = SSL_write(cl->ssl, buf, size);
- cl->ssl_err = SSL_get_error(cl->ssl, num);
-
- if (cl->fd_handler)
- {
- if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
- else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
- ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
- }
-
- if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
- (cl->ssl_err == SSL_ERROR_SYSCALL) ||
- (cl->ssl_err == SSL_ERROR_SSL))
- return -1;
-
- if (num < 0)
- return 0;
-
- return num;
-}
-
-#else
-
-/*
- * No Ssl
- */
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr EINA_UNUSED,
- int ssl_type EINA_UNUSED)
-{
- return ECORE_CON_SSL_ERROR_NONE;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_init_none(Ecore_Con_Server *svr EINA_UNUSED)
-{
- return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cafile_add_none(Ecore_Con_Server *svr EINA_UNUSED,
- const char *ca_file EINA_UNUSED)
-{
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_cert_add_none(Ecore_Con_Server *svr EINA_UNUSED,
- const char *cert_file EINA_UNUSED)
-{
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_privkey_add_none(Ecore_Con_Server *svr EINA_UNUSED,
- const char *key_file EINA_UNUSED)
-{
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_ecore_con_ssl_server_crl_add_none(Ecore_Con_Server *svr EINA_UNUSED,
- const char *crl_file EINA_UNUSED)
-{
- return EINA_FALSE;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr EINA_UNUSED)
-{
- return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
-}
-
-static int
-_ecore_con_ssl_server_read_none(Ecore_Con_Server *svr EINA_UNUSED,
- unsigned char *buf EINA_UNUSED,
- int size EINA_UNUSED)
-{
- return -1;
-}
-
-static int
-_ecore_con_ssl_server_write_none(Ecore_Con_Server *svr EINA_UNUSED,
- const unsigned char *buf EINA_UNUSED,
- int size EINA_UNUSED)
-{
- return -1;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_init_none(Ecore_Con_Client *cl EINA_UNUSED)
-{
- return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
-}
-
-static Ecore_Con_Ssl_Error
-_ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl EINA_UNUSED)
-{
- return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
-}
-
-static int
-_ecore_con_ssl_client_read_none(Ecore_Con_Client *cl EINA_UNUSED,
- unsigned char *buf EINA_UNUSED,
- int size EINA_UNUSED)
-{
- return -1;
-}
-
-static int
-_ecore_con_ssl_client_write_none(Ecore_Con_Client *cl EINA_UNUSED,
- const unsigned char *buf EINA_UNUSED,
- int size EINA_UNUSED)
-{
- return -1;
-}
-
-#endif
diff --git a/src/lib/ecore_con/efl_network.eo b/src/lib/ecore_con/efl_network.eo
deleted file mode 100644
index 2f95a0584f..0000000000
--- a/src/lib/ecore_con/efl_network.eo
+++ /dev/null
@@ -1,201 +0,0 @@
-type Ecore_Con_Dns_Cb: __undefined_type; [[Ecore connection DNS callback type]]
-
-enum Ecore.Con.Type
-{
- [[Types for an ecore_con client/server object. A correct way to set this type is
- with an ECORE_CON_$TYPE, optionally OR'ed with an ECORE_CON_$USE if encryption is desired,
- and LOAD_CERT if the previously loaded certificate should be used.]]
- legacy: ecore_con;
-
- local_user = 0, [[Socket in "~/.ecore"]]
- local_system = 1, [[Socket in /tmp]]
- local_abstract = 2, [[Abstract socket]]
- remote_tcp = 3, [[Remote server using TCP]]
- remote_mcast = 4, [[Remote multicast server]]
- remote_udp = 5, [[Remote server using UDP]]
- remote_broadcasT = 6, [[Remote broadcast using UDP]]
- remote_nodelay = 7, [[Remote connection sending packets immediately]]
- remote_cork = 8, [[Remote connection sending data in large chunks
- Note: Only available on Linux
- @since 1.2]]
- use_ssl2 = (1 << 4), [[Use SSL2: UNSUPPORTED.]]
- use_ssl3 = (1 << 5), [[Use SSL3: UNSUPPORTED.]]
- use_tls = (1 << 6), [[Use TLS]]
- use_mixed = Ecore.Con.Type.use_tls | Ecore.Con.Type.use_ssl3, [[Use both TLS and SSL3]]
- load_cert = (1 << 7), [[Attempt to use the loaded certificate]]
- no_proxy = (1 << 8), [[Disable all types of proxy on the server
- Note: Only functional for clients
- @since 1.2]]
- socket_activate = (1 << 9) [[Indicate if the type is socket activated]]
-}
-
-abstract Efl.Network (Efl.Object) {
- [[Abstract base class for all EFL.Network classes]]
-
- legacy_prefix: ecore_con;
- eo_prefix: efl_network;
- data: null;
- methods {
- @property ip {
- [[Control the IP address of a server that has been connected to.
-
- The parameter is a pointer to an internal string that contains the IP
- address of the connected server in the form "XXX.YYY.ZZZ.AAA" IP
- notation. This string should not be modified or trusted to stay
- valid after deletion for the svr object. If no IP is known
- null is returned.
- ]]
- get @virtual_pure {
- legacy: null;
- }
- values {
- ip: string; [[The IP address]]
- }
- }
- @property uptime {
- [[Check how long the object has been connected
-
- This function is used to find out how long a client has been
- connected.
- ]]
- get @virtual_pure {
- legacy: null;
- }
- values {
- uptime: double; [[The total time, in seconds, that the object has been connected.]]
- }
- }
- @property port @virtual_pure {
- [[The port that the obj is connected to]]
- set {
- legacy: null;
- }
- get {
- legacy: null;
- }
- values {
- port: int; [[The port that obj is connected to, or -1 on error.]]
- }
- }
- @property fd {
- [[Get the fd that the server is connected to
-
- This function returns the fd which is used by the underlying server
- connection. It should not be tampered with unless you REALLY know
- what you are doing.
-
- Note: This function is only valid for servers created with
- \@ref ecore_con_server_connect.
-
- Warning: Seriously. Don't use this unless you know what you are doing.
-
- @since 1.1
- ]]
- get @virtual_pure {
- legacy: null;
- }
- values {
- fd: int; [[The fd, or -1 on failure.]]
- }
- }
- @property connected {
- [[Returns whether the client is still connected]]
- get @virtual_pure {
- legacy: null;
- }
- values {
- connected: bool; [[$true if connected, $false otherwise.]]
- }
- }
- @property timeout @virtual_pure {
- [[Control the default time after which an inactive client will be
- disconnected.
-
- This function is used by the server to set the default idle timeout
- on clients. If any of the clients becomes idle for a time higher
- than this value, it will be disconnected. A value of < 1 disables
- the idle timeout.
-
- This timeout is not affected by the one set by @.timeout.set. A
- client will be disconnected whenever the client or the server
- timeout is reached. That means, the lower timeout value will be
- used for that client if @.timeout.set is used on it.
- ]]
- set {
- legacy: null;
- }
- get {
- legacy: null;
- }
- values {
- timeout: double; [[The timeout, in seconds, to disconnect after.]]
- }
- }
- flush @virtual_pure {
- [[Flushes all pending data to the given server.
-
- This function will block until all data is sent to the server.
- ]]
- legacy: null;
- }
- send @virtual_pure {
- [[Sends the given data to the given server.
-
- This function will send the given data to the server as soon as the
- program is back to the main loop. Thus, this function returns
- immediately (non-blocking). If the data needs to be sent now, call
- \@ref ecore_con_server_flush after this one.
- ]]
- legacy: null;
-
- params {
- data: const(void_ptr); [[The given data]]
- size: int; [[Length of the data, in bytes.]]
- }
- return: int; [[The number of bytes sent. 0 will be returned if there
- is an error.]]
- }
- lookup @class {
- [[Do an asynchronous DNS lookup.
-
- This function performs a DNS lookup on the hostname specified by name,
- then calls done_cb with the result and the data given as parameter.
- The result will be given to the done_cb as follows:
-
- canonname - the canonical name of the address, ip - the resolved ip
- address, addr - a pointer to the socket address, addrlen - the length
- of the socket address, in bytes, data - the data pointer given as
- parameter.
- ]]
- params {
- name: string @nonull; [[IP address or server name to translate.]]
- done_cb: Ecore_Con_Dns_Cb; [[Callback to notify when done.]]
- data: const(void_ptr); [[User data to be given to done_cb.]]
- }
- return: bool; [[$true if the request did not fail to be set up, $false otherwise.]]
- }
- }
- events {
- data,received: Ecore.Con.Event_Data.Received; [[Data received on connection]]
- connection,upgraded; [[FIXME: what does upgrade mean here??]]
- connection,error: string; [[Error received on connection]]
- }
-}
-
-/* FIXME: Should actually be a binbuf. */
-struct Ecore.Con.Event_Data.Received {
- [[Ecore connection event data received data structure]]
- data: void_ptr; [[The data that got sent.]]
- size: int; [[The length of the data sent.]]
-}
-
-/* TODO
-* Add events (to all of the ecore con stuff, e.g url).
-* Make server the father of the client - make sure I don't leak references.
-*
-* Still need to add constructor client, and most likely migrate ecore_con_eet.
-*
-* Split server to two classes, listener and connector (or w/e).
-*
-* Mark the constructing properties all around.
-*/
diff --git a/src/lib/ecore_con/efl_network_client.eo b/src/lib/ecore_con/efl_network_client.eo
deleted file mode 100644
index bf3f6c2f32..0000000000
--- a/src/lib/ecore_con/efl_network_client.eo
+++ /dev/null
@@ -1,30 +0,0 @@
-class Efl.Network.Client (Efl.Network) {
- [[Efl network client]]
- legacy_prefix: ecore_con_client;
- eo_prefix: efl_network_client_obj;
- methods {
- @property server {
- [[The server the client is connected to.]]
- get {
- }
- values {
- svr: Efl.Network.Server; [[The server the client is connected to.]]
- }
- }
- }
- implements {
- Efl.Object.destructor;
- Efl.Network.ip.get;
- Efl.Network.uptime.get;
- Efl.Network.port.get;
- Efl.Network.fd.get;
- Efl.Network.connected.get;
- Efl.Network.timeout.set;
- Efl.Network.timeout.get;
- Efl.Network.flush;
- Efl.Network.send;
- }
-}
-
-/* FIXME: Should SSL inherit from client? What's exactly the interaction here?
- Fix clients to be children of server when created .*/
diff --git a/src/lib/ecore_con/efl_network_connector.eo b/src/lib/ecore_con/efl_network_connector.eo
deleted file mode 100644
index 5b3e27e321..0000000000
--- a/src/lib/ecore_con/efl_network_connector.eo
+++ /dev/null
@@ -1,8 +0,0 @@
-class Efl.Network.Connector (Efl.Network.Server) {
- [[Efl network connector class]]
- eo_prefix: efl_network_connector_obj;
- data: null;
- implements {
- Efl.Object.finalize;
- }
-}
diff --git a/src/lib/ecore_con/efl_network_server.eo b/src/lib/ecore_con/efl_network_server.eo
deleted file mode 100644
index 972e262ffa..0000000000
--- a/src/lib/ecore_con/efl_network_server.eo
+++ /dev/null
@@ -1,93 +0,0 @@
-class Efl.Network.Server (Efl.Network) {
- [[Efl network server]]
- legacy_prefix: ecore_con_server;
- eo_prefix: efl_network_server;
- methods {
- @property name {
- [[Retrieves the name of server.
-
- The name returned is the name used to connect on this server.
- ]]
- set {
- legacy: null;
- }
- get {
- }
- values {
- name: string; [[The name of the server.]]
- }
- }
- @property client_limit {
- [[Sets a limit on the number of clients that can be handled concurrently
- by the given server, and a policy on what to do if excess clients
- try to connect.
-
- Beware that if you set this once ecore is already running, you may
- already have pending CLIENT_ADD events in your event queue. Those
- clients have already connected and will not be affected by this call.
- Only clients subsequently trying to connect will be affected.
- ]]
- set {
- }
- get {
- legacy: null;
- }
- values {
- client_limit: int; [[The maximum number of clients to handle
- concurrently. -1 means unlimited (default).
- 0 effectively disables the server.]]
- reject_excess_clients: char; [[Set to 1 to automatically disconnect excess clients as
- soon as they connect if you are already handling
- client_limit clients. Set to 0 (default) to just
- hold off on the "accept()" system call until the
- number of active clients drops. This causes the
- kernel to queue up to 4096 connections (or your
- kernel's limit, whichever is lower).
- ]]
- }
- }
- /* FIXME: Should this return an iterator? */
- @property clients {
- [[Retrieves the current list of clients.
-
- Each node in the returned list points to an \@ref Efl_Network_Client.
- This list cannot be modified or freed. It can also change if new
- clients are connected or disconnected, and will become invalid
- when the server is deleted/freed.
- ]]
- get {
- }
- values {
- // FIXME: Efl.Network.Client is needed, but that introduces a cycle
- clients: const(list<const(Efl.Network)>); [[The list of clients on this server.]]
- }
- }
- @property connection_type {
- [[Type of the server connection as defined in @Ecore.Con.Type]]
- get {
- legacy: null;
- }
- set {
- legacy: null;
- }
- values {
- conn_type: Ecore.Con.Type; [[Connection type]]
- }
- }
- }
- implements {
- Efl.Object.constructor;
- Efl.Object.destructor;
- Efl.Object.finalize;
- Efl.Network.ip.get;
- Efl.Network.uptime.get;
- Efl.Network.port.set;
- Efl.Network.port.get;
- Efl.Network.fd.get;
- Efl.Network.connected.get;
- Efl.Network.timeout.set;
- Efl.Network.timeout.get;
- Efl.Network.flush;
- Efl.Network.send;
- }
-}