2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2010-01-04 15:43:16 -08:00
|
|
|
#include <stdio.h>
|
2010-01-16 05:44:25 -08:00
|
|
|
#include <string.h>
|
2009-11-20 02:58:19 -08:00
|
|
|
#include <sys/types.h>
|
2003-09-23 01:09:32 -07:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
2013-03-15 01:12:05 -07:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
# include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_TCP_H
|
|
|
|
# include <netinet/tcp.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
2013-01-10 12:26:02 -08:00
|
|
|
#include <sys/un.h>
|
2013-03-15 01:12:05 -07:00
|
|
|
#endif
|
2010-02-20 11:12:52 -08:00
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
# include <systemd/sd-daemon.h>
|
|
|
|
#endif
|
|
|
|
|
2010-02-20 11:12:52 -08:00
|
|
|
#ifdef HAVE_WS2TCPIP_H
|
|
|
|
# include <ws2tcpip.h>
|
|
|
|
#endif
|
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Ecore.h"
|
|
|
|
#include "ecore_private.h"
|
|
|
|
#include "Ecore_Con.h"
|
|
|
|
#include "ecore_con_private.h"
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
#ifndef MSG_NOSIGNAL
|
|
|
|
#define MSG_NOSIGNAL 0 /* noop */
|
|
|
|
#endif
|
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
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);
|
2014-08-22 05:14:59 -07:00
|
|
|
static void _ecore_con_client_flush(Ecore_Con_Client *obj);
|
2013-12-19 21:07:50 -08:00
|
|
|
|
|
|
|
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);
|
2010-11-16 13:32:50 -08:00
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
#define EO_CONSTRUCTOR_CHECK_RETURN(obj) do { \
|
2016-08-10 07:23:04 -07:00
|
|
|
if (efl_finalized_get(obj)) \
|
2014-08-28 06:17:16 -07:00
|
|
|
{ \
|
|
|
|
ERR("This function is only allowed during construction."); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
int sd_fd_index = 0;
|
|
|
|
int sd_fd_max = 0;
|
|
|
|
#endif
|
2011-12-21 02:13:57 -08:00
|
|
|
|
2012-01-19 00:02:41 -08:00
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_kill(Ecore_Con_Client *obj)
|
2011-12-21 02:13:57 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-12-21 02:13:57 -08:00
|
|
|
if (cl->delete_me)
|
|
|
|
DBG("Multi kill request for client %p", cl);
|
|
|
|
else
|
2012-02-22 00:50:43 -08:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_del(obj);
|
2012-02-22 00:50:43 -08:00
|
|
|
if (cl->buf) return;
|
|
|
|
}
|
2011-12-21 02:13:57 -08:00
|
|
|
INF("Lost client %s", (cl->ip) ? cl->ip : "");
|
|
|
|
if (cl->fd_handler)
|
2012-06-06 02:49:24 -07:00
|
|
|
ecore_main_fd_handler_del(cl->fd_handler);
|
|
|
|
|
|
|
|
cl->fd_handler = NULL;
|
2011-12-21 02:13:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(Ecore_Con_Server *obj)
|
2011-12-21 02:13:57 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-12-21 02:13:57 -08:00
|
|
|
if (svr->delete_me)
|
|
|
|
DBG("Multi kill request for svr %p", svr);
|
|
|
|
else
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_del(obj);
|
2011-12-21 02:13:57 -08:00
|
|
|
|
|
|
|
if (svr->fd_handler)
|
2012-06-06 02:49:24 -07:00
|
|
|
ecore_main_fd_handler_del(svr->fd_handler);
|
|
|
|
|
|
|
|
svr->fd_handler = NULL;
|
2011-12-21 02:13:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define _ecore_con_server_kill(svr) do { \
|
2013-12-19 21:07:50 -08:00
|
|
|
DBG("KILL %p", (svr)); \
|
|
|
|
_ecore_con_server_kill((svr)); \
|
|
|
|
} while (0)
|
2011-12-21 02:13:57 -08:00
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
#define _ecore_con_client_kill(cl) do { \
|
|
|
|
DBG("KILL %p", (cl)); \
|
|
|
|
_ecore_con_client_kill((cl)); \
|
|
|
|
} while (0)
|
2011-12-21 02:13:57 -08:00
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
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;
|
2011-09-13 16:03:26 -07:00
|
|
|
EAPI int ECORE_CON_EVENT_CLIENT_WRITE = 0;
|
|
|
|
EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
|
2011-02-10 00:49:23 -08:00
|
|
|
EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
|
|
|
|
EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
|
2011-12-05 19:32:16 -08:00
|
|
|
EAPI int ECORE_CON_EVENT_PROXY_BIND = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2016-09-09 16:09:51 -07:00
|
|
|
EAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_CONNECT = 0;
|
|
|
|
EAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY = 0;
|
|
|
|
EAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST = 0;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EAPI Eina_Error EFL_NET_DIALER_ERROR_PROXY_AUTHENTICATION_FAILED = 0;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
* estickies,
* etk,
* PROTO/exalt,
* E-MODULES-EXTRA/diskio,
* E-MODULES-EXTRA/drawer,
* E-MODULES-EXTRA/penguins,
* E-MODULES-EXTRA/slideshow,
* E-MODULES-EXTRA/mail,
* E-MODULES-EXTRA/forecasts,
* E-MODULES-EXTRA/iiirk,
* E-MODULES-EXTRA/places,
* e,
* ewl,
* ecore,
* elitaire,
* entrance,
* e_dbus,
* efreet: Here we go, move from Ecore_List to Eina_List.
NOTE: This patch is huge, I did test it a lot, and I hope nothing is
broken. But if you think something change after this commit, please
contact me ASAP.
SVN revision: 39200
2009-02-25 03:03:47 -08:00
|
|
|
static Eina_List *servers = NULL;
|
2009-10-09 22:28:43 -07:00
|
|
|
static int _ecore_con_init_count = 0;
|
2011-11-10 18:44:16 -08:00
|
|
|
static int _ecore_con_event_count = 0;
|
2009-12-21 09:32:19 -08:00
|
|
|
int _ecore_con_log_dom = -1;
|
2011-12-05 19:32:16 -08:00
|
|
|
Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
|
|
|
|
Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2016-09-20 11:00:17 -07:00
|
|
|
typedef struct pxProxyFactory_ pxProxyFactory;
|
|
|
|
typedef struct _Ecore_Con_Libproxy {
|
|
|
|
pxProxyFactory *factory;
|
|
|
|
char **(*px_proxy_factory_get_proxies)(pxProxyFactory *factory, const char *url);
|
|
|
|
void *(*px_proxy_factory_new)(void);
|
|
|
|
void (*px_proxy_factory_free)(pxProxyFactory *);
|
|
|
|
Eina_Module *mod;
|
|
|
|
} Ecore_Con_Libproxy;
|
|
|
|
static Ecore_Con_Libproxy _ecore_con_libproxy;
|
2016-09-18 23:19:16 -07:00
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_con_init(void)
|
|
|
|
{
|
2009-10-09 22:28:43 -07:00
|
|
|
if (++_ecore_con_init_count != 1)
|
2010-11-03 10:58:37 -07:00
|
|
|
return _ecore_con_init_count;
|
2009-10-09 22:28:43 -07:00
|
|
|
|
2010-01-14 23:44:27 -08:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
if (!evil_init())
|
2010-11-03 10:58:37 -07:00
|
|
|
return --_ecore_con_init_count;
|
2010-01-14 23:44:27 -08:00
|
|
|
#endif
|
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
if (!ecore_init())
|
2015-02-05 02:26:58 -08:00
|
|
|
goto ecore_err;
|
2005-09-07 02:06:06 -07:00
|
|
|
|
2010-10-07 15:31:46 -07:00
|
|
|
_ecore_con_log_dom = eina_log_domain_register
|
2010-11-03 10:58:37 -07:00
|
|
|
("ecore_con", ECORE_CON_DEFAULT_LOG_COLOR);
|
2010-11-05 18:22:50 -07:00
|
|
|
if (_ecore_con_log_dom < 0)
|
2015-02-05 02:26:58 -08:00
|
|
|
goto ecore_con_log_error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_mempool_init();
|
|
|
|
|
2005-09-07 02:06:06 -07:00
|
|
|
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();
|
2011-09-13 16:03:26 -07:00
|
|
|
ECORE_CON_EVENT_CLIENT_WRITE = ecore_event_type_new();
|
|
|
|
ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
|
2011-02-10 00:49:23 -08:00
|
|
|
ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
|
|
|
|
ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
|
2011-12-05 19:32:16 -08:00
|
|
|
ECORE_CON_EVENT_PROXY_BIND = ecore_event_type_new();
|
2004-03-31 08:47:45 -08:00
|
|
|
|
2016-09-09 16:09:51 -07:00
|
|
|
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");
|
|
|
|
EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST = eina_error_msg_static_register("Couldn't resolve host name");
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EFL_NET_DIALER_ERROR_PROXY_AUTHENTICATION_FAILED = eina_error_msg_static_register("Proxy authentication failed");
|
2016-09-09 16:09:51 -07:00
|
|
|
|
2010-11-06 10:04:09 -07:00
|
|
|
eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
|
2012-06-22 05:17:59 -07:00
|
|
|
eina_magic_string_set(ECORE_MAGIC_CON_CLIENT, "Ecore_Con_Client");
|
2010-11-06 10:04:09 -07:00
|
|
|
eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
|
|
|
|
|
2005-09-07 02:06:06 -07:00
|
|
|
/* TODO Remember return value, if it fails, use gethostbyname() */
|
2011-12-05 19:32:16 -08:00
|
|
|
ecore_con_socks_init();
|
2008-10-30 08:26:11 -07:00
|
|
|
ecore_con_ssl_init();
|
2008-10-09 05:30:19 -07:00
|
|
|
ecore_con_info_init();
|
2015-03-06 06:52:43 -08:00
|
|
|
ecore_con_local_init();
|
2005-09-07 02:06:06 -07:00
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
sd_fd_max = sd_listen_fds(0);
|
|
|
|
#endif
|
|
|
|
|
2013-03-27 05:42:55 -07:00
|
|
|
eina_log_timing(_ecore_con_log_dom,
|
2013-12-19 21:07:50 -08:00
|
|
|
EINA_LOG_STATE_STOP,
|
|
|
|
EINA_LOG_STATE_INIT);
|
2013-03-27 05:42:55 -07:00
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
return _ecore_con_init_count;
|
2015-02-05 02:26:58 -08:00
|
|
|
|
|
|
|
ecore_con_log_error:
|
|
|
|
EINA_LOG_ERR("Failed to create a log domain for Ecore Con.");
|
|
|
|
ecore_shutdown();
|
|
|
|
|
|
|
|
ecore_err:
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
evil_shutdown();
|
|
|
|
#endif
|
|
|
|
return --_ecore_con_init_count;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_con_shutdown(void)
|
|
|
|
{
|
2010-11-11 12:34:35 -08:00
|
|
|
Eina_List *l, *l2;
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj;
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2014-10-29 05:24:53 -07:00
|
|
|
/* _ecore_con_init_count should not go below zero. */
|
|
|
|
if (_ecore_con_init_count < 1)
|
|
|
|
{
|
|
|
|
ERR("Ecore_Con Shutdown called without calling Ecore_Con Init.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2009-10-09 22:28:43 -07:00
|
|
|
if (--_ecore_con_init_count != 0)
|
2010-11-03 10:58:37 -07:00
|
|
|
return _ecore_con_init_count;
|
2010-01-28 08:07:33 -08:00
|
|
|
|
2016-09-20 11:00:17 -07:00
|
|
|
if (_ecore_con_libproxy.factory)
|
2016-09-18 23:19:16 -07:00
|
|
|
{
|
2016-09-20 11:00:17 -07:00
|
|
|
_ecore_con_libproxy.px_proxy_factory_free(_ecore_con_libproxy.factory);
|
|
|
|
_ecore_con_libproxy.factory = NULL;
|
|
|
|
}
|
|
|
|
if (_ecore_con_libproxy.mod)
|
|
|
|
{
|
|
|
|
eina_module_free(_ecore_con_libproxy.mod);
|
|
|
|
_ecore_con_libproxy.mod = NULL;
|
2016-09-18 23:19:16 -07:00
|
|
|
}
|
|
|
|
|
2013-03-27 05:42:55 -07:00
|
|
|
eina_log_timing(_ecore_con_log_dom,
|
2013-12-19 21:07:50 -08:00
|
|
|
EINA_LOG_STATE_START,
|
|
|
|
EINA_LOG_STATE_SHUTDOWN);
|
2013-03-27 05:42:55 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EINA_LIST_FOREACH_SAFE(servers, l, l2, obj)
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-11-10 18:44:16 -08:00
|
|
|
Ecore_Con_Event_Server_Add *ev;
|
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if (!svr) continue;
|
2011-12-21 02:02:30 -08:00
|
|
|
svr->delete_me = EINA_TRUE;
|
2011-12-02 19:50:20 -08:00
|
|
|
INF("svr %p is dead", svr);
|
2011-11-10 18:44:16 -08:00
|
|
|
/* some pointer hacks here to prevent double frees if people are being stupid */
|
|
|
|
EINA_LIST_FREE(svr->event_count, ev)
|
|
|
|
ev->server = NULL;
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_free(obj);
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2005-09-07 02:06:06 -07:00
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
ecore_con_socks_shutdown();
|
2011-11-10 18:44:16 -08:00
|
|
|
if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
|
2011-11-06 04:26:00 -08:00
|
|
|
|
2015-03-06 06:52:43 -08:00
|
|
|
ecore_con_local_shutdown();
|
2008-10-09 05:30:19 -07:00
|
|
|
ecore_con_info_shutdown();
|
2008-10-30 08:26:11 -07:00
|
|
|
ecore_con_ssl_shutdown();
|
2009-12-21 09:32:19 -08:00
|
|
|
eina_log_domain_unregister(_ecore_con_log_dom);
|
|
|
|
_ecore_con_log_dom = -1;
|
2006-01-19 01:11:30 -08:00
|
|
|
ecore_shutdown();
|
2010-01-14 23:44:27 -08:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
evil_shutdown();
|
|
|
|
#endif
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2009-10-09 22:28:43 -07:00
|
|
|
return _ecore_con_init_count;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2010-09-20 23:49:07 -07:00
|
|
|
|
2014-08-22 03:11:41 -07:00
|
|
|
EOLIAN static Eina_Bool
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_lookup(Eo *kls_obj EINA_UNUSED, void *pd EINA_UNUSED, const char *name, Ecore_Con_Dns_Cb done_cb, const void *data)
|
2010-09-20 23:49:07 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj;
|
2010-09-20 23:49:07 -07:00
|
|
|
Ecore_Con_Lookup *lk;
|
|
|
|
struct addrinfo hints;
|
|
|
|
|
|
|
|
if (!name || !done_cb)
|
2010-11-03 10:58:37 -07:00
|
|
|
return EINA_FALSE;
|
2010-09-20 23:49:07 -07:00
|
|
|
|
2016-09-05 08:57:35 -07:00
|
|
|
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));
|
2010-09-20 23:49:07 -07:00
|
|
|
|
|
|
|
lk = malloc(sizeof (Ecore_Con_Lookup));
|
|
|
|
if (!lk)
|
|
|
|
{
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
lk->done_cb = done_cb;
|
|
|
|
lk->data = data;
|
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
ecore_con_server_data_set(obj, lk);
|
2010-09-20 23:49:07 -07:00
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(struct addrinfo));
|
2011-07-04 13:04:18 -07:00
|
|
|
hints.ai_family = AF_UNSPEC;
|
2010-09-20 23:49:07 -07:00
|
|
|
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;
|
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
if (ecore_con_info_get(obj, _ecore_con_lookup_done, obj,
|
2010-09-20 23:49:07 -07:00
|
|
|
&hints))
|
2010-11-03 10:58:37 -07:00
|
|
|
return EINA_TRUE;
|
2010-09-20 23:49:07 -07:00
|
|
|
|
|
|
|
free(lk);
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_del(obj);
|
2010-09-20 23:49:07 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2004-09-22 01:17:15 -07:00
|
|
|
/**
|
2010-07-28 17:27:15 -07:00
|
|
|
* @addtogroup Ecore_Con_Server_Group Ecore Connection Server Functions
|
2004-09-22 01:17:15 -07:00
|
|
|
*
|
|
|
|
* Functions that operate on Ecore server objects.
|
2010-09-20 23:49:07 -07:00
|
|
|
*
|
2010-07-28 17:27:15 -07:00
|
|
|
* @{
|
2004-09-22 01:17:15 -07:00
|
|
|
*/
|
|
|
|
|
2010-09-20 23:49:07 -07:00
|
|
|
/**
|
|
|
|
* @example ecore_con_server_example.c
|
|
|
|
* Shows how to write a simple server using the Ecore_Con library.
|
2010-11-03 10:58:37 -07:00
|
|
|
*/
|
2010-09-20 23:49:07 -07:00
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Con_Server *
|
2010-09-20 23:49:07 -07:00
|
|
|
ecore_con_server_add(Ecore_Con_Type compl_type,
|
2013-12-19 21:07:50 -08:00
|
|
|
const char *name,
|
|
|
|
int port,
|
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
|
|
|
|
/* remote system socket: TCP/IP: [name]:[port] */
|
2016-09-05 08:57:35 -07:00
|
|
|
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));
|
2014-08-28 06:17:16 -07:00
|
|
|
|
|
|
|
ecore_con_server_data_set(obj, (void *) data);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:41:27 -07:00
|
|
|
EOLIAN static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_network_server_efl_object_constructor(Ecore_Con_Server *obj, Efl_Network_Server_Data *svr)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_constructor(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2014-08-11 04:48:03 -07:00
|
|
|
svr->fd = -1;
|
2010-09-17 23:30:13 -07:00
|
|
|
svr->reject_excess_clients = EINA_FALSE;
|
2008-10-09 05:30:19 -07:00
|
|
|
svr->client_limit = -1;
|
2008-12-11 05:55:47 -08:00
|
|
|
svr->clients = NULL;
|
2015-05-19 03:41:27 -07:00
|
|
|
|
|
|
|
return obj;
|
2014-08-28 06:17:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_network_server_efl_object_finalize(Ecore_Con_Server *obj, Efl_Network_Server_Data *svr)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
|
|
|
Ecore_Con_Type compl_type = svr->type;
|
|
|
|
Ecore_Con_Type type;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_finalize(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
|
2014-08-28 06:17:16 -07:00
|
|
|
|
|
|
|
svr->created = EINA_TRUE;
|
2008-10-09 05:30:19 -07:00
|
|
|
svr->ppid = getpid();
|
2014-08-28 06:17:16 -07:00
|
|
|
svr->start_time = ecore_time_get();
|
|
|
|
svr->use_cert = (svr->type & ECORE_CON_SSL & ECORE_CON_LOAD_CERT) == ECORE_CON_LOAD_CERT;
|
2014-08-11 04:48:03 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
servers = eina_list_append(servers, obj);
|
2014-08-12 16:44:44 -07:00
|
|
|
|
2015-03-06 07:26:24 -08:00
|
|
|
if (!svr->name)
|
2014-08-11 04:48:03 -07:00
|
|
|
goto error;
|
|
|
|
|
2015-03-07 06:53:40 -08:00
|
|
|
type = compl_type & ECORE_CON_TYPE;
|
|
|
|
|
2015-03-06 07:26:24 -08:00
|
|
|
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);
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
if (ecore_con_ssl_server_prepare(obj, compl_type & ECORE_CON_SSL))
|
2010-09-18 12:29:43 -07:00
|
|
|
goto error;
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
if ((type == ECORE_CON_LOCAL_USER) ||
|
2010-05-15 20:04:18 -07:00
|
|
|
(type == ECORE_CON_LOCAL_SYSTEM) ||
|
2006-09-24 00:53:47 -07:00
|
|
|
(type == ECORE_CON_LOCAL_ABSTRACT))
|
2013-12-19 21:07:50 -08:00
|
|
|
/* Local */
|
2011-05-14 10:52:30 -07:00
|
|
|
#ifdef _WIN32
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_local_listen(obj))
|
2011-05-14 10:52:30 -07:00
|
|
|
goto error;
|
|
|
|
#else
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_local_listen(obj, _ecore_con_svr_tcp_handler, obj))
|
2010-11-03 10:58:37 -07:00
|
|
|
goto error;
|
2011-05-14 10:52:30 -07:00
|
|
|
#endif
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
if ((type == ECORE_CON_REMOTE_TCP) ||
|
2011-12-10 00:14:50 -08:00
|
|
|
(type == ECORE_CON_REMOTE_NODELAY) ||
|
|
|
|
(type == ECORE_CON_REMOTE_CORK))
|
2008-09-17 08:08:48 -07:00
|
|
|
{
|
2008-10-09 05:30:19 -07:00
|
|
|
/* TCP */
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_info_tcp_listen(obj, _ecore_con_cb_tcp_listen,
|
|
|
|
obj))
|
2013-12-19 21:07:50 -08:00
|
|
|
goto error;
|
2004-04-14 01:51:19 -07:00
|
|
|
}
|
2010-05-15 20:04:18 -07:00
|
|
|
else if ((type == ECORE_CON_REMOTE_MCAST) ||
|
|
|
|
(type == ECORE_CON_REMOTE_UDP))
|
2010-11-03 10:58:37 -07:00
|
|
|
/* UDP and MCAST */
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_info_udp_listen(obj, _ecore_con_cb_udp_listen,
|
|
|
|
obj))
|
2010-11-03 10:58:37 -07:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
return obj;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2014-08-11 04:48:03 -07:00
|
|
|
if (svr->delete_me) return NULL;
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(obj);
|
2003-09-23 01:09:32 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Con_Server *
|
2010-09-20 23:49:07 -07:00
|
|
|
ecore_con_server_connect(Ecore_Con_Type compl_type,
|
2013-12-19 21:07:50 -08:00
|
|
|
const char *name,
|
|
|
|
int port,
|
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj;
|
2010-09-18 12:26:05 -07:00
|
|
|
/* local user socket: FILE: ~/.ecore/[name]/[port] */
|
2003-09-23 01:09:32 -07:00
|
|
|
/* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
|
|
|
|
/* remote system socket: TCP/IP: [name]:[port] */
|
2016-09-05 08:57:35 -07:00
|
|
|
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));
|
2014-08-28 06:17:16 -07:00
|
|
|
|
|
|
|
ecore_con_server_data_set(obj, (void *) data);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_network_connector_efl_object_finalize(Ecore_Con_Server *obj, void *pd EINA_UNUSED)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2014-08-28 06:17:16 -07:00
|
|
|
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. */
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_finalize(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2011-12-10 00:09:17 -08:00
|
|
|
svr->use_cert = (compl_type & ECORE_CON_SSL & ECORE_CON_LOAD_CERT) == ECORE_CON_LOAD_CERT;
|
2012-06-04 02:16:19 -07:00
|
|
|
svr->disable_proxy = (compl_type & ECORE_CON_SUPER_SSL & ECORE_CON_NO_PROXY) == ECORE_CON_NO_PROXY;
|
2014-08-22 08:06:27 -07:00
|
|
|
servers = eina_list_append(servers, obj);
|
2014-08-12 16:44:44 -07:00
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
if (!svr->name || !(svr->name[0]))
|
2014-08-11 04:48:03 -07:00
|
|
|
goto error;
|
|
|
|
|
2008-10-09 05:30:19 -07:00
|
|
|
type = compl_type & ECORE_CON_TYPE;
|
|
|
|
|
2012-06-04 02:03:04 -07:00
|
|
|
if ((!svr->disable_proxy) && (type > ECORE_CON_LOCAL_ABSTRACT))
|
2011-12-05 19:32:16 -08:00
|
|
|
{
|
|
|
|
/* 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)
|
2012-02-14 21:53:50 -08:00
|
|
|
svr->ecs_state = ECORE_CON_PROXY_STATE_RESOLVED;
|
2011-12-05 19:32:16 -08:00
|
|
|
}
|
|
|
|
}
|
2014-08-22 08:06:27 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_GOTO(ecore_con_ssl_server_prepare(obj, compl_type & ECORE_CON_SSL), error);
|
2011-12-05 19:32:16 -08:00
|
|
|
|
2012-06-28 01:51:06 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_GOTO(((type == ECORE_CON_REMOTE_TCP) ||
|
2013-12-19 21:07:50 -08:00
|
|
|
(type == ECORE_CON_REMOTE_NODELAY) ||
|
|
|
|
(type == ECORE_CON_REMOTE_CORK) ||
|
|
|
|
(type == ECORE_CON_REMOTE_UDP) ||
|
|
|
|
(type == ECORE_CON_REMOTE_BROADCAST)) &&
|
2015-03-06 07:26:24 -08:00
|
|
|
(svr->port < 0), error);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
if ((type == ECORE_CON_LOCAL_USER) ||
|
2010-05-15 20:04:18 -07:00
|
|
|
(type == ECORE_CON_LOCAL_SYSTEM) ||
|
2006-09-24 00:53:47 -07:00
|
|
|
(type == ECORE_CON_LOCAL_ABSTRACT))
|
2013-12-19 21:07:50 -08:00
|
|
|
/* Local */
|
2011-05-14 10:52:30 -07:00
|
|
|
#ifdef _WIN32
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_local_connect(obj, _ecore_con_cl_handler)) goto error;
|
2011-05-14 10:52:30 -07:00
|
|
|
#else
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_local_connect(obj, _ecore_con_cl_handler, obj)) goto error;
|
2011-05-14 10:52:30 -07:00
|
|
|
#endif
|
2004-03-31 08:47:45 -08:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
if ((type == ECORE_CON_REMOTE_TCP) ||
|
2011-12-10 00:14:50 -08:00
|
|
|
(type == ECORE_CON_REMOTE_NODELAY) ||
|
|
|
|
(type == ECORE_CON_REMOTE_CORK))
|
2006-01-19 01:11:30 -08:00
|
|
|
{
|
2008-10-09 05:30:19 -07:00
|
|
|
/* TCP */
|
2014-08-22 08:06:27 -07:00
|
|
|
EINA_SAFETY_ON_FALSE_GOTO(ecore_con_info_tcp_connect(obj, _ecore_con_cb_tcp_connect, obj), error);
|
2006-01-19 01:11:30 -08:00
|
|
|
}
|
2012-06-28 01:51:06 -07:00
|
|
|
else if ((type == ECORE_CON_REMOTE_UDP) || (type == ECORE_CON_REMOTE_BROADCAST))
|
2010-11-03 10:58:37 -07:00
|
|
|
/* UDP and MCAST */
|
2014-08-22 08:06:27 -07:00
|
|
|
EINA_SAFETY_ON_FALSE_GOTO(ecore_con_info_udp_connect(obj, _ecore_con_cb_udp_connect, obj), error);
|
2005-09-02 20:07:29 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
return obj;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2003-09-23 01:09:32 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-09-21 21:48:09 -07:00
|
|
|
EAPI void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_timeout_set(Ecore_Con *obj, double timeout)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
efl_network_timeout_set((Ecore_Con *)obj, timeout);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static void
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_timeout_set(Eo *obj, Efl_Network_Server_Data *svr, double timeout)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2011-06-17 04:16:50 -07:00
|
|
|
if (svr->created)
|
|
|
|
svr->client_disconnect_time = timeout;
|
|
|
|
else
|
|
|
|
svr->disconnect_time = timeout;
|
2013-07-17 07:20:45 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_timeout_get(const Ecore_Con *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_timeout_get((Ecore_Con *)obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static double
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_timeout_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2011-06-17 04:16:50 -07:00
|
|
|
return svr->created ? svr->client_disconnect_time : svr->disconnect_time;
|
2010-09-21 21:48:09 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_del(Ecore_Con_Server *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!obj) return NULL;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-10-07 07:28:17 -07:00
|
|
|
if (!svr || svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return NULL;
|
* estickies,
* etk,
* PROTO/exalt,
* E-MODULES-EXTRA/diskio,
* E-MODULES-EXTRA/drawer,
* E-MODULES-EXTRA/penguins,
* E-MODULES-EXTRA/slideshow,
* E-MODULES-EXTRA/mail,
* E-MODULES-EXTRA/forecasts,
* E-MODULES-EXTRA/iiirk,
* E-MODULES-EXTRA/places,
* e,
* ewl,
* ecore,
* elitaire,
* entrance,
* e_dbus,
* efreet: Here we go, move from Ecore_List to Eina_List.
NOTE: This patch is huge, I did test it a lot, and I hope nothing is
broken. But if you think something change after this commit, please
contact me ASAP.
SVN revision: 39200
2009-02-25 03:03:47 -08:00
|
|
|
|
2015-01-30 05:16:59 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
WSASendDisconnect(svr->fd, NULL);
|
|
|
|
#endif
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(obj);
|
2011-12-09 21:42:32 -08:00
|
|
|
return svr->data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_data_get(Ecore_Con_Server *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!svr)
|
|
|
|
return NULL;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
return svr->data;
|
|
|
|
}
|
|
|
|
|
2010-07-28 17:27:15 -07:00
|
|
|
EAPI void *
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_data_set(Ecore_Con_Server *obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *data)
|
2010-07-28 17:27:15 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2014-10-07 07:28:17 -07:00
|
|
|
void *ret = NULL;
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!svr)
|
|
|
|
return NULL;
|
2010-07-28 17:27:15 -07:00
|
|
|
|
|
|
|
ret = svr->data;
|
|
|
|
svr->data = data;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-09-20 18:48:46 -07:00
|
|
|
EAPI Eina_Bool
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_connected_get(const Ecore_Con *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_connected_get((Ecore_Con *)obj);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static Eina_Bool
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_connected_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2006-03-29 22:48:45 -08:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
return !svr->connecting;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2016-01-12 22:19:07 -08:00
|
|
|
EOLIAN static const Eina_List *
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_clients_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2006-03-29 22:48:45 -08:00
|
|
|
return svr->clients;
|
|
|
|
}
|
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
EOLIAN static void
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_connection_type_set(Eo *obj, Efl_Network_Server_Data *svr, Ecore_Con_Type type)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
|
|
|
EO_CONSTRUCTOR_CHECK_RETURN(obj);
|
|
|
|
|
|
|
|
svr->type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Ecore_Con_Type
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_connection_type_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
|
|
|
return svr->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_name_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, const char *name)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
|
|
|
EO_CONSTRUCTOR_CHECK_RETURN(obj);
|
|
|
|
|
|
|
|
if (svr->name)
|
|
|
|
free(svr->name);
|
|
|
|
|
|
|
|
svr->name = strdup(name);
|
|
|
|
}
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static const char *
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_name_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2010-08-26 22:16:00 -07:00
|
|
|
{
|
|
|
|
return svr->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_port_get(const Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_port_get((Ecore_Con *)obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
|
|
|
|
2014-08-28 06:17:16 -07:00
|
|
|
EOLIAN static void
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_port_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, int port)
|
2014-08-28 06:17:16 -07:00
|
|
|
{
|
|
|
|
EO_CONSTRUCTOR_CHECK_RETURN(obj);
|
|
|
|
|
|
|
|
svr->port = port;
|
|
|
|
}
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_port_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2010-08-26 22:16:00 -07:00
|
|
|
{
|
|
|
|
return svr->port;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_send(Ecore_Con *obj, const void *data, int size)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_send((Ecore_Con *)obj, data, size);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_send(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr, const void *data, int size)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2011-12-21 02:02:30 -08:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->delete_me, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 09:11:12 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 09:11:12 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2005-09-22 22:46:56 -07:00
|
|
|
if (svr->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-07-16 06:07:39 -07:00
|
|
|
if (!svr->buf)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-07-16 06:07:39 -07:00
|
|
|
svr->buf = eina_binbuf_new();
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(svr->buf, 0);
|
2011-12-10 00:14:50 -08:00
|
|
|
#ifdef TCP_CORK
|
|
|
|
if ((svr->fd >= 0) && ((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
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2014-04-04 03:35:16 -07:00
|
|
|
if (!eina_binbuf_append_length(svr->buf, data, size))
|
|
|
|
ERR("eina_binbuf_append_length() failed");
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2004-04-23 00:24:40 -07:00
|
|
|
return size;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-09-22 01:17:15 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static void
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_client_limit_set(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr,
|
2013-12-19 21:07:50 -08:00
|
|
|
int client_limit,
|
|
|
|
char reject_excess_clients)
|
2005-04-28 21:51:31 -07:00
|
|
|
{
|
|
|
|
svr->client_limit = client_limit;
|
|
|
|
svr->reject_excess_clients = reject_excess_clients;
|
|
|
|
}
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static void
|
2016-02-04 23:09:53 -08:00
|
|
|
_efl_network_server_client_limit_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr,
|
2014-08-22 08:06:27 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-07-28 15:32:39 -07:00
|
|
|
EAPI const char *
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_ip_get(const Ecore_Con *obj)
|
2006-03-19 23:45:58 -08:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_ip_get(obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static const char *
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_ip_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2006-03-19 23:45:58 -08:00
|
|
|
return svr->ip;
|
|
|
|
}
|
|
|
|
|
2010-09-21 21:48:09 -07:00
|
|
|
EAPI double
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_uptime_get(const Ecore_Con *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_uptime_get(obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static double
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_uptime_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
2010-09-21 21:48:09 -07:00
|
|
|
return ecore_time_get() - svr->start_time;
|
|
|
|
}
|
2010-11-03 10:58:37 -07:00
|
|
|
|
2007-02-16 10:12:38 -08:00
|
|
|
EAPI void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_flush(Ecore_Con *obj)
|
2007-02-16 10:12:38 -08:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
efl_network_flush((Ecore_Con *)obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
EOLIAN static void
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_flush(Eo *obj, Efl_Network_Server_Data *svr EINA_UNUSED)
|
2014-08-22 08:06:27 -07:00
|
|
|
{
|
|
|
|
_ecore_con_server_flush(obj);
|
2007-02-16 10:12:38 -08:00
|
|
|
}
|
|
|
|
|
2010-07-28 17:27:15 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup Ecore_Con_Client_Group Ecore Connection Client Functions
|
2004-09-22 01:17:15 -07:00
|
|
|
*
|
|
|
|
* Functions that operate on Ecore connection client objects.
|
2010-09-20 23:49:07 -07:00
|
|
|
*
|
2010-07-28 17:27:15 -07:00
|
|
|
* @{
|
2004-09-22 01:17:15 -07:00
|
|
|
*/
|
|
|
|
|
2010-09-20 23:49:07 -07:00
|
|
|
/**
|
|
|
|
* @example ecore_con_client_example.c
|
|
|
|
* Shows how to write a simple client that connects to the example server.
|
2010-11-03 10:58:37 -07:00
|
|
|
*/
|
2010-09-20 23:49:07 -07:00
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_client_send(Ecore_Con *obj, const void *data, int size)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_send((Ecore_Con *)obj, data, size);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_send(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl, const void *data, int size)
|
2014-08-22 05:14:59 -07:00
|
|
|
{
|
2016-02-04 23:09:53 -08:00
|
|
|
Efl_Network_Server_Data *host_server = NULL;
|
2011-12-21 02:02:30 -08:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->delete_me, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 09:11:12 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 09:11:12 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2005-09-22 22:46:56 -07:00
|
|
|
if (cl->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
if (cl->host_server)
|
2016-08-15 06:44:41 -07:00
|
|
|
host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_CLIENT_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
|
|
|
|
|
|
|
if (cl->host_server && ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP))
|
2014-08-26 22:49:47 -07:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = (int)sendto(host_server->fd, data, size, 0,
|
|
|
|
(struct sockaddr *)cl->client_addr,
|
|
|
|
cl->client_addr_len);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else
|
2008-10-09 05:30:19 -07:00
|
|
|
{
|
2014-01-03 09:57:56 -08:00
|
|
|
if (!cl->buf)
|
2011-12-10 00:14:50 -08:00
|
|
|
{
|
2014-01-03 09:57:56 -08:00
|
|
|
cl->buf = eina_binbuf_new();
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cl->buf, 0);
|
|
|
|
#ifdef TCP_CORK
|
2014-09-04 01:57:19 -07:00
|
|
|
if ((cl->fd >= 0) && (host_server) &&
|
2014-08-27 01:16:17 -07:00
|
|
|
((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK))
|
2014-01-03 09:57:56 -08:00
|
|
|
{
|
|
|
|
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));
|
|
|
|
}
|
2011-12-10 00:14:50 -08:00
|
|
|
#endif
|
2014-01-03 09:57:56 -08:00
|
|
|
}
|
2014-04-04 03:35:16 -07:00
|
|
|
if (!eina_binbuf_append_length(cl->buf, data, size))
|
|
|
|
ERR("eina_binbuf_append_length() failed");
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-04-23 00:24:40 -07:00
|
|
|
return size;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static Ecore_Con_Server *
|
2016-02-12 12:02:01 -08:00
|
|
|
_efl_network_client_server_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-18 12:26:05 -07:00
|
|
|
return cl->host_server;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static Eina_Bool
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_connected_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2010-11-05 17:17:04 -07:00
|
|
|
{
|
2011-12-21 02:02:30 -08:00
|
|
|
return !cl->delete_me;
|
2010-11-05 17:17:04 -07:00
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
ecore_con_client_connected_get(const Ecore_Con *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_connected_get((Ecore_Con *)obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static void
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_timeout_set(Eo *obj, Efl_Network_Client_Data *cl, double timeout)
|
2014-08-22 05:14:59 -07:00
|
|
|
{
|
2010-09-21 21:48:09 -07:00
|
|
|
cl->disconnect_time = timeout;
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI void
|
|
|
|
ecore_con_client_timeout_set(Ecore_Con *obj, double timeout)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
efl_network_timeout_set((Ecore_Con *)obj, timeout);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static double
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_timeout_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2014-08-22 05:14:59 -07:00
|
|
|
{
|
2010-09-21 21:48:09 -07:00
|
|
|
return cl->disconnect_time;
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI double
|
|
|
|
ecore_con_client_timeout_get(const Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_timeout_get((Ecore_Con *)obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_client_del(Ecore_Con_Client *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
if (!obj) return NULL;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!cl) return NULL;
|
2012-05-24 00:49:30 -07:00
|
|
|
|
2015-01-30 05:16:59 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
WSASendDisconnect(cl->fd, NULL);
|
|
|
|
#endif
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_kill(obj);
|
2012-06-06 02:49:24 -07:00
|
|
|
return cl->data;
|
2012-05-24 00:49:30 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_client_data_set(Ecore_Con_Client *obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2014-08-22 05:14:59 -07:00
|
|
|
if (!cl)
|
|
|
|
return;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
cl->data = (void *)data;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_client_data_get(Ecore_Con_Client *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2014-08-22 05:14:59 -07:00
|
|
|
if (!cl)
|
|
|
|
return NULL;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
return cl->data;
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static const char *
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_ip_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2006-03-19 23:45:58 -08:00
|
|
|
{
|
2010-11-16 13:32:50 -08:00
|
|
|
if (!cl->ip)
|
2011-09-29 14:05:20 -07:00
|
|
|
cl->ip = _ecore_con_pretty_ip(cl->client_addr);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2006-03-19 23:45:58 -08:00
|
|
|
return cl->ip;
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI const char *
|
|
|
|
ecore_con_client_ip_get(const Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_ip_get(obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_port_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2011-02-10 23:38:27 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *sd = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-05-14 09:19:57 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-02-10 23:38:27 -08:00
|
|
|
if (cl->client_addr->sa_family == AF_INET)
|
2013-12-19 21:07:50 -08:00
|
|
|
return ((struct sockaddr_in *)cl->client_addr)->sin_port;
|
2011-09-29 14:04:54 -07:00
|
|
|
#ifdef HAVE_IPV6
|
2013-12-19 21:07:50 -08:00
|
|
|
return ((struct sockaddr_in6 *)cl->client_addr)->sin6_port;
|
2011-09-29 14:04:54 -07:00
|
|
|
#else
|
|
|
|
return -1;
|
|
|
|
#endif
|
2011-02-10 23:38:27 -08:00
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI int
|
|
|
|
ecore_con_client_port_get(const Ecore_Con *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_port_get((Ecore_Con *)obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static double
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_uptime_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2014-08-22 05:14:59 -07:00
|
|
|
{
|
2010-09-21 21:48:09 -07:00
|
|
|
return ecore_time_get() - cl->start_time;
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI double
|
|
|
|
ecore_con_client_uptime_get(const Ecore_Con *obj)
|
2007-02-16 10:12:38 -08:00
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_uptime_get(obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_flush(Eo *obj, Efl_Network_Client_Data *cl EINA_UNUSED)
|
2014-08-22 05:14:59 -07:00
|
|
|
{
|
|
|
|
_ecore_con_client_flush(obj);
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI void
|
|
|
|
ecore_con_client_flush(Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
efl_network_flush((Ecore_Con *)obj);
|
2007-02-16 10:12:38 -08:00
|
|
|
}
|
|
|
|
|
2011-09-12 01:30:22 -07:00
|
|
|
EAPI int
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_fd_get(const Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_fd_get((Ecore_Con *)obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_server_efl_network_fd_get(Eo *obj EINA_UNUSED, Efl_Network_Server_Data *svr)
|
2011-09-12 01:30:22 -07:00
|
|
|
{
|
|
|
|
if (svr->created) return -1;
|
2012-09-13 00:04:11 -07:00
|
|
|
if (svr->delete_me) return -1;
|
2011-09-12 01:30:22 -07:00
|
|
|
return ecore_main_fd_handler_fd_get(svr->fd_handler);
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EOLIAN static int
|
2016-05-11 05:00:57 -07:00
|
|
|
_efl_network_client_efl_network_fd_get(Eo *obj EINA_UNUSED, Efl_Network_Client_Data *cl)
|
2011-09-12 01:30:22 -07:00
|
|
|
{
|
|
|
|
return ecore_main_fd_handler_fd_get(cl->fd_handler);
|
|
|
|
}
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EAPI int
|
|
|
|
ecore_con_client_fd_get(const Ecore_Con *obj)
|
|
|
|
{
|
2016-05-11 05:00:57 -07:00
|
|
|
return efl_network_fd_get((Ecore_Con *)obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
|
|
|
|
2010-07-28 17:27:15 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_proxy_bind(Ecore_Con_Server *obj)
|
2011-12-05 19:32:16 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2013-12-19 21:07:50 -08:00
|
|
|
Ecore_Con_Event_Proxy_Bind *e;
|
|
|
|
int ev = ECORE_CON_EVENT_PROXY_BIND;
|
2011-12-05 19:32:16 -08:00
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
e = ecore_con_event_proxy_bind_alloc();
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
2011-12-05 19:32:16 -08:00
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
svr->event_count = eina_list_append(svr->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
|
|
|
e->server = obj;
|
2013-12-19 21:07:50 -08:00
|
|
|
e->ip = svr->proxyip;
|
|
|
|
e->port = svr->proxyport;
|
|
|
|
ecore_event_add(ev, e,
|
|
|
|
_ecore_con_event_server_add_free, NULL);
|
2011-12-05 19:32:16 -08:00
|
|
|
_ecore_con_event_count++;
|
|
|
|
}
|
|
|
|
|
2011-02-10 11:17:30 -08:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_add(Ecore_Con_Server *obj)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2013-12-19 21:07:50 -08:00
|
|
|
/* 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);
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
|
|
|
e->server = obj;
|
2013-12-19 21:07:50 -08:00
|
|
|
if (svr->upgrade) ev = ECORE_CON_EVENT_SERVER_UPGRADE;
|
|
|
|
ecore_event_add(ev, e,
|
|
|
|
_ecore_con_event_server_add_free, NULL);
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_UPGRADED, NULL);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_del(Ecore_Con_Server *obj)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2013-12-19 21:07:50 -08:00
|
|
|
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);
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
|
|
|
e->server = obj;
|
2013-12-19 21:07:50 -08:00
|
|
|
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);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
2011-09-13 16:03:26 -07:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_write(Ecore_Con_Server *obj, int num)
|
2011-09-13 16:03:26 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-09-13 16:03:26 -07:00
|
|
|
Ecore_Con_Event_Server_Write *e;
|
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
e = ecore_con_event_server_write_alloc();
|
2011-09-13 16:03:26 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
INF("Wrote %d bytes", num);
|
2011-11-10 18:44:16 -08:00
|
|
|
svr->event_count = eina_list_append(svr->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
e->server = obj;
|
2011-09-13 16:03:26 -07:00
|
|
|
e->size = num;
|
|
|
|
ecore_event_add(ECORE_CON_EVENT_SERVER_WRITE, e,
|
|
|
|
(Ecore_End_Cb)_ecore_con_event_server_write_free, NULL);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-09-13 16:03:26 -07:00
|
|
|
}
|
|
|
|
|
2011-02-10 11:17:30 -08:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_data(Ecore_Con_Server *obj, unsigned char *buf, int num, Eina_Bool duplicate)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-02-10 11:17:30 -08:00
|
|
|
Ecore_Con_Event_Server_Data *e;
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
e = ecore_con_event_server_data_alloc();
|
2011-12-09 23:34:45 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
svr->event_count = eina_list_append(svr->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
|
|
|
e->server = obj;
|
2011-05-14 10:52:30 -07:00
|
|
|
if (duplicate)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2011-05-14 10:52:30 -07:00
|
|
|
e->data = malloc(num);
|
|
|
|
if (!e->data)
|
|
|
|
{
|
2011-11-06 04:26:00 -08:00
|
|
|
ERR("server data allocation failure !");
|
|
|
|
_ecore_con_event_server_data_free(NULL, e);
|
2011-05-14 10:52:30 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
memcpy(e->data, buf, num);
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
2011-05-14 10:52:30 -07:00
|
|
|
else
|
|
|
|
e->data = buf;
|
2011-02-10 11:17:30 -08:00
|
|
|
e->size = num;
|
|
|
|
ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
|
|
|
|
_ecore_con_event_server_data_free, NULL);
|
2014-08-22 08:38:25 -07:00
|
|
|
{
|
2015-04-21 04:03:33 -07:00
|
|
|
Ecore_Con_Event_Data_Received event_info = { NULL, 0 };
|
2014-08-22 08:38:25 -07:00
|
|
|
event_info.data = e->data;
|
|
|
|
event_info.size = e->size;
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_DATA_RECEIVED, &event_info);
|
2014-08-22 08:38:25 -07:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_add(Ecore_Con_Client *obj)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-02-10 11:17:30 -08:00
|
|
|
Ecore_Con_Event_Client_Add *e;
|
2011-06-15 11:58:34 -07:00
|
|
|
int ev = ECORE_CON_EVENT_CLIENT_ADD;
|
2011-02-10 11:17:30 -08:00
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
e = ecore_con_event_client_add_alloc();
|
2011-02-10 11:17:30 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
cl->event_count = eina_list_append(cl->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
host_server->event_count = eina_list_append(host_server->event_count, e);
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
2013-05-24 05:06:08 -07:00
|
|
|
cl->start_time = ecore_time_get();
|
2014-08-22 05:14:59 -07:00
|
|
|
e->client = obj;
|
2011-06-15 11:58:34 -07:00
|
|
|
if (cl->upgrade) ev = ECORE_CON_EVENT_CLIENT_UPGRADE;
|
|
|
|
ecore_event_add(ev, e,
|
2011-02-10 11:17:30 -08:00
|
|
|
(Ecore_End_Cb)_ecore_con_event_client_add_free, cl->host_server);
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_UPGRADED, NULL);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_del(Ecore_Con_Client *obj)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2013-12-19 21:07:50 -08:00
|
|
|
Ecore_Con_Event_Client_Del *e;
|
2011-02-10 11:17:30 -08:00
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
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);
|
2011-02-10 11:17:30 -08:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
|
|
|
host_server->event_count = eina_list_append(host_server->event_count, e);
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
|
|
|
e->client = obj;
|
2013-12-19 21:07:50 -08:00
|
|
|
ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
|
|
|
|
(Ecore_End_Cb)_ecore_con_event_client_del_free, cl->host_server);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
2011-09-13 16:03:26 -07:00
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_write(Ecore_Con_Client *obj, int num)
|
2011-09-13 16:03:26 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-09-13 16:03:26 -07:00
|
|
|
Ecore_Con_Event_Client_Write *e;
|
2011-11-06 04:26:00 -08:00
|
|
|
|
|
|
|
e = ecore_con_event_client_write_alloc();
|
2011-09-13 16:03:26 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
cl->event_count = eina_list_append(cl->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
host_server->event_count = eina_list_append(host_server->event_count, e);
|
2014-08-22 05:14:59 -07:00
|
|
|
e->client = obj;
|
2011-09-13 16:03:26 -07:00
|
|
|
e->size = num;
|
|
|
|
ecore_event_add(ECORE_CON_EVENT_CLIENT_WRITE, e,
|
|
|
|
(Ecore_End_Cb)_ecore_con_event_client_write_free, cl->host_server);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-09-13 16:03:26 -07:00
|
|
|
}
|
|
|
|
|
2011-02-10 11:17:30 -08:00
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_data(Ecore_Con_Client *obj, unsigned char *buf, int num, Eina_Bool duplicate)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-02-10 11:17:30 -08:00
|
|
|
Ecore_Con_Event_Client_Data *e;
|
2011-11-06 04:26:00 -08:00
|
|
|
|
|
|
|
e = ecore_con_event_client_data_alloc();
|
2011-02-10 11:17:30 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
cl->event_count = eina_list_append(cl->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
host_server->event_count = eina_list_append(host_server->event_count, e);
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
|
|
|
e->client = obj;
|
2013-11-18 03:48:00 -08:00
|
|
|
if ((duplicate) && (num > 0))
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2011-05-14 10:52:30 -07:00
|
|
|
e->data = malloc(num);
|
|
|
|
if (!e->data)
|
|
|
|
{
|
2011-11-06 04:26:00 -08:00
|
|
|
ERR("client data allocation failure !");
|
|
|
|
_ecore_con_event_client_data_free(cl->host_server, e);
|
2011-05-14 10:52:30 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
memcpy(e->data, buf, num);
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
2011-05-14 10:52:30 -07:00
|
|
|
else
|
|
|
|
e->data = buf;
|
2011-02-10 11:17:30 -08:00
|
|
|
e->size = num;
|
|
|
|
ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
|
|
|
|
(Ecore_End_Cb)_ecore_con_event_client_data_free, cl->host_server);
|
2014-08-22 06:33:26 -07:00
|
|
|
{
|
2015-04-21 04:03:33 -07:00
|
|
|
Ecore_Con_Event_Data_Received event_info = { NULL, 0 };
|
2014-08-22 06:33:26 -07:00
|
|
|
event_info.data = e->data;
|
|
|
|
event_info.size = e->size;
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_DATA_RECEIVED, &event_info);
|
2014-08-22 06:33:26 -07:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
2011-01-21 02:01:04 -08:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_infos_del(Ecore_Con_Server *obj, void *info)
|
2011-01-21 02:01:04 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-01-21 02:01:04 -08:00
|
|
|
svr->infos = eina_list_remove(svr->infos, info);
|
|
|
|
}
|
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_server_error(Ecore_Con_Server *obj, char *error, Eina_Bool duplicate)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-02-10 00:49:23 -08:00
|
|
|
Ecore_Con_Event_Server_Error *e;
|
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
e = ecore_con_event_server_error_alloc();
|
2011-02-10 00:49:23 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
e->server = obj;
|
2011-12-09 21:09:47 -08:00
|
|
|
e->error = duplicate ? strdup(error) : error;
|
2013-01-04 00:45:31 -08:00
|
|
|
DBG("%s", error);
|
2011-11-10 18:44:16 -08:00
|
|
|
svr->event_count = eina_list_append(svr->event_count, e);
|
2011-02-10 00:49:23 -08:00
|
|
|
ecore_event_add(ECORE_CON_EVENT_SERVER_ERROR, e, (Ecore_End_Cb)_ecore_con_event_server_error_free, NULL);
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_ERROR, e->error);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_error(Ecore_Con_Client *obj, const char *error)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-02-10 00:49:23 -08:00
|
|
|
Ecore_Con_Event_Client_Error *e;
|
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
e = ecore_con_event_client_error_alloc();
|
2011-02-10 00:49:23 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(e);
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
e->client = obj;
|
2011-02-10 00:49:23 -08:00
|
|
|
e->error = strdup(error);
|
2013-01-04 00:45:31 -08:00
|
|
|
DBG("%s", error);
|
2011-11-10 18:44:16 -08:00
|
|
|
cl->event_count = eina_list_append(cl->event_count, e);
|
2014-08-22 08:06:27 -07:00
|
|
|
host_server->event_count = eina_list_append(host_server->event_count, e);
|
2011-02-10 11:17:30 -08:00
|
|
|
ecore_event_add(ECORE_CON_EVENT_CLIENT_ERROR, e, (Ecore_End_Cb)_ecore_con_event_client_error_free, cl->host_server);
|
2016-08-29 16:13:22 -07:00
|
|
|
efl_event_callback_call(obj, EFL_NETWORK_EVENT_CONNECTION_ERROR, e->error);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count++;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_free(Ecore_Con_Server *obj)
|
|
|
|
{
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_del(obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_network_server_efl_object_destructor(Eo *obj, Efl_Network_Server_Data *svr)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
Ecore_Con_Client *cl_obj;
|
2006-05-18 20:52:24 -07:00
|
|
|
double t_start, t;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2014-08-29 02:07:14 -07:00
|
|
|
if (svr->event_count) goto end;
|
2011-11-19 16:28:48 -08:00
|
|
|
|
2011-01-21 02:01:04 -08:00
|
|
|
while (svr->infos)
|
|
|
|
{
|
|
|
|
ecore_con_info_data_clear(svr->infos->data);
|
|
|
|
svr->infos = eina_list_remove_list(svr->infos, svr->infos);
|
|
|
|
}
|
2010-11-11 12:20:44 -08:00
|
|
|
|
2006-05-18 20:52:24 -07:00
|
|
|
t_start = ecore_time_get();
|
2011-12-21 02:02:30 -08:00
|
|
|
while (svr->buf && (!svr->delete_me))
|
2006-05-18 20:52:24 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_flush(obj);
|
2010-07-26 23:30:27 -07:00
|
|
|
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;
|
|
|
|
}
|
2006-05-18 20:52:24 -07:00
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2011-05-14 10:52:30 -07:00
|
|
|
#ifdef _WIN32
|
2014-08-26 03:07:43 -07:00
|
|
|
ecore_con_local_win32_server_del(obj);
|
2011-05-14 10:52:30 -07:00
|
|
|
#endif
|
2014-08-29 02:07:14 -07:00
|
|
|
if (svr->event_count) goto end;
|
2011-05-14 10:52:30 -07:00
|
|
|
|
2011-07-16 06:07:39 -07:00
|
|
|
if (svr->buf)
|
|
|
|
eina_binbuf_free(svr->buf);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
EINA_LIST_FREE(svr->clients, cl_obj)
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(cl_obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-11-10 18:44:16 -08:00
|
|
|
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;
|
2011-12-21 02:02:30 -08:00
|
|
|
cl->delete_me = EINA_TRUE;
|
2011-12-02 19:50:20 -08:00
|
|
|
INF("cl %p is dead", cl);
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_free(cl_obj);
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2008-10-09 05:30:19 -07:00
|
|
|
if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
|
2010-11-03 10:58:37 -07:00
|
|
|
unlink(svr->path);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
2011-11-10 18:44:16 -08:00
|
|
|
free(svr->name);
|
2015-06-24 21:18:22 -07:00
|
|
|
svr->name = NULL;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
free(svr->path);
|
2015-06-24 21:18:22 -07:00
|
|
|
svr->path = NULL;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
eina_stringshare_del(svr->ip);
|
2011-12-07 17:14:55 -08:00
|
|
|
eina_stringshare_del(svr->verify_name);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
if (svr->ecs_buf) eina_binbuf_free(svr->ecs_buf);
|
|
|
|
if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
if (svr->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_del(svr->fd_handler);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-11 04:48:03 -07:00
|
|
|
if (svr->fd >= 0)
|
2010-12-15 20:38:37 -08:00
|
|
|
close(svr->fd);
|
|
|
|
|
2011-06-17 04:16:50 -07:00
|
|
|
if (svr->until_deletion)
|
|
|
|
ecore_timer_del(svr->until_deletion);
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
servers = eina_list_remove(servers, obj);
|
2010-11-11 11:53:21 -08:00
|
|
|
svr->data = NULL;
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_destructor(efl_super(obj, EFL_NETWORK_SERVER_CLASS));
|
2015-06-24 21:18:22 -07:00
|
|
|
end:
|
|
|
|
return;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_free(Ecore_Con_Client *obj)
|
|
|
|
{
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_del(obj);
|
2014-08-22 05:14:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_network_client_efl_object_destructor(Eo *obj, Efl_Network_Client_Data *cl)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2006-05-18 20:52:24 -07:00
|
|
|
double t_start, t;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
if (cl->event_count) return;
|
2010-12-08 22:43:58 -08:00
|
|
|
|
2006-05-18 20:52:24 -07:00
|
|
|
t_start = ecore_time_get();
|
2011-12-21 02:02:30 -08:00
|
|
|
while ((cl->buf) && (!cl->delete_me))
|
2006-05-18 20:52:24 -07:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_flush(obj);
|
2010-07-26 23:30:27 -07:00
|
|
|
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;
|
|
|
|
}
|
2006-05-18 20:52:24 -07:00
|
|
|
}
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2016-04-05 00:32:25 -07:00
|
|
|
if (host_server)
|
|
|
|
{
|
|
|
|
host_server->clients = eina_list_remove(host_server->clients, obj);
|
|
|
|
--host_server->client_count;
|
|
|
|
}
|
2011-05-14 10:52:30 -07:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
2014-08-26 03:07:43 -07:00
|
|
|
ecore_con_local_win32_client_del(obj);
|
2011-05-14 10:52:30 -07:00
|
|
|
#endif
|
|
|
|
|
2011-11-19 16:28:48 -08:00
|
|
|
if (cl->event_count) return;
|
|
|
|
|
2012-02-24 03:21:12 -08:00
|
|
|
if (cl->buf) eina_binbuf_free(cl->buf);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2016-04-05 00:32:25 -07:00
|
|
|
if (host_server && (host_server->type & ECORE_CON_SSL))
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_ssl_client_shutdown(obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
if (cl->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_del(cl->fd_handler);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-11 04:48:03 -07:00
|
|
|
if (cl->fd >= 0)
|
2010-12-15 20:38:37 -08:00
|
|
|
close(cl->fd);
|
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
free(cl->client_addr);
|
2010-12-02 22:14:30 -08:00
|
|
|
cl->client_addr = NULL;
|
|
|
|
|
2011-06-17 04:16:50 -07:00
|
|
|
if (cl->until_deletion)
|
|
|
|
ecore_timer_del(cl->until_deletion);
|
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
eina_stringshare_del(cl->ip);
|
2010-11-11 11:53:21 -08:00
|
|
|
cl->data = NULL;
|
2014-08-22 05:14:59 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_destructor(efl_super(obj, EFL_NETWORK_CLIENT_CLASS));
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2011-06-17 04:16:50 -07:00
|
|
|
static Eina_Bool
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer(Ecore_Con_Server *obj)
|
2011-06-17 04:16:50 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_server_del(obj);
|
2011-06-17 04:16:50 -07:00
|
|
|
|
2011-07-07 11:18:53 -07:00
|
|
|
svr->until_deletion = NULL;
|
2011-06-17 04:16:50 -07:00
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(Ecore_Con_Server *obj)
|
2011-06-17 04:16:50 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-06-17 04:16:50 -07:00
|
|
|
if (svr->disconnect_time)
|
|
|
|
{
|
|
|
|
if (svr->disconnect_time > 0)
|
|
|
|
{
|
|
|
|
if (svr->until_deletion)
|
2013-05-24 02:51:09 -07:00
|
|
|
{
|
|
|
|
ecore_timer_interval_set(svr->until_deletion, svr->disconnect_time);
|
|
|
|
ecore_timer_reset(svr->until_deletion);
|
|
|
|
}
|
2011-06-17 04:16:50 -07:00
|
|
|
else
|
2014-08-22 08:06:27 -07:00
|
|
|
svr->until_deletion = ecore_timer_add(svr->disconnect_time, (Ecore_Task_Cb)_ecore_con_server_timer, obj);
|
2011-06-17 04:16:50 -07:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-21 21:48:09 -07:00
|
|
|
static Eina_Bool
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_timer(Ecore_Con_Client *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_client_del(obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
|
2011-07-07 11:18:53 -07:00
|
|
|
cl->until_deletion = NULL;
|
2010-09-21 21:48:09 -07:00
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(Ecore_Con_Client *obj)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2010-09-21 21:48:09 -07:00
|
|
|
if (cl->disconnect_time)
|
|
|
|
{
|
|
|
|
if (cl->disconnect_time > 0)
|
|
|
|
{
|
|
|
|
if (cl->until_deletion)
|
2013-05-24 02:51:09 -07:00
|
|
|
{
|
|
|
|
ecore_timer_interval_set(cl->until_deletion, cl->disconnect_time);
|
|
|
|
ecore_timer_reset(cl->until_deletion);
|
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
else
|
2014-12-30 02:17:32 -08:00
|
|
|
cl->until_deletion = ecore_timer_add(cl->disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
}
|
|
|
|
else if (cl->until_deletion)
|
|
|
|
{
|
|
|
|
ecore_timer_del(cl->until_deletion);
|
|
|
|
cl->until_deletion = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
|
2016-04-05 00:32:25 -07:00
|
|
|
if (host_server && host_server->client_disconnect_time > 0)
|
2010-09-21 21:48:09 -07:00
|
|
|
{
|
|
|
|
if (cl->until_deletion)
|
2013-05-24 04:53:07 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_timer_interval_set(cl->until_deletion, host_server->client_disconnect_time);
|
2013-05-24 04:53:07 -07:00
|
|
|
ecore_timer_reset(cl->until_deletion);
|
|
|
|
}
|
2010-09-21 21:48:09 -07:00
|
|
|
else
|
2014-12-30 02:17:32 -08:00
|
|
|
cl->until_deletion = ecore_timer_add(host_server->client_disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, obj);
|
2010-09-21 21:48:09 -07:00
|
|
|
}
|
|
|
|
else if (cl->until_deletion)
|
|
|
|
{
|
|
|
|
ecore_timer_del(cl->until_deletion);
|
|
|
|
cl->until_deletion = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-06 02:41:39 -07:00
|
|
|
static void
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cb_tcp_listen(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Con_Info *net_info)
|
2008-10-09 05:30:19 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2008-10-09 05:30:19 -07:00
|
|
|
struct linger lin;
|
2011-12-09 21:17:34 -08:00
|
|
|
const char *memerr = NULL;
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
errno = 0;
|
2011-02-10 00:49:23 -08:00
|
|
|
if (!net_info) /* error message has already been handled */
|
2012-07-02 02:24:02 -07:00
|
|
|
{
|
|
|
|
svr->delete_me = EINA_TRUE;
|
|
|
|
goto error;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#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,
|
2013-12-19 21:07:50 -08:00
|
|
|
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;
|
2013-03-09 22:49:54 -08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
|
|
|
|
net_info->info.ai_protocol);
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd == INVALID_SOCKET) goto error;
|
|
|
|
|
2015-01-30 01:51:52 -08:00
|
|
|
if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
|
|
|
|
#else
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd < 0) goto error;
|
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
|
|
|
|
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
|
2015-01-30 01:51:52 -08:00
|
|
|
#endif
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2008-10-09 05:30:19 -07:00
|
|
|
lin.l_onoff = 1;
|
|
|
|
lin.l_linger = 0;
|
2010-07-26 23:30:27 -07:00
|
|
|
if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
|
|
|
|
sizeof(struct linger)) < 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-07-30 10:03:34 -07:00
|
|
|
if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
|
2009-11-20 02:58:19 -08:00
|
|
|
{
|
2013-12-19 21:07:50 -08:00
|
|
|
int flag = 1;
|
2009-11-20 02:58:19 -08:00
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
|
|
|
|
sizeof(int)) < 0)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
|
|
|
goto error;
|
|
|
|
}
|
2009-11-20 02:58:19 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2015-01-30 05:25:53 -08:00
|
|
|
if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) != 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
|
|
|
|
2015-01-30 05:25:53 -08:00
|
|
|
if (listen(svr->fd, 4096) != 0) goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#ifdef HAVE_SYSTEMD
|
2013-12-19 21:07:50 -08:00
|
|
|
fd_ready:
|
2013-03-09 22:49:54 -08:00
|
|
|
#endif
|
2010-09-17 23:06:05 -07:00
|
|
|
svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_svr_tcp_handler, obj, NULL, NULL);
|
2010-07-26 23:30:27 -07:00
|
|
|
if (!svr->fd_handler)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:17:34 -08:00
|
|
|
memerr = "Memory allocation failure";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2008-10-09 05:30:19 -07:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2014-08-22 08:06:27 -07:00
|
|
|
if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
|
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
|
|
|
_ecore_con_server_kill(obj);
|
2008-10-09 05:30:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cb_udp_listen(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Con_Info *net_info)
|
2008-10-09 05:30:19 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2008-10-09 05:30:19 -07:00
|
|
|
Ecore_Con_Type type;
|
|
|
|
struct ip_mreq mreq;
|
2011-09-29 14:04:54 -07:00
|
|
|
#ifdef HAVE_IPV6
|
2008-10-09 05:30:19 -07:00
|
|
|
struct ipv6_mreq mreq6;
|
2011-09-29 14:04:54 -07:00
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
const int on = 1;
|
2011-12-09 21:17:34 -08:00
|
|
|
const char *memerr = NULL;
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
|
|
|
|
type = svr->type;
|
|
|
|
type &= ECORE_CON_TYPE;
|
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
errno = 0;
|
2011-02-10 00:49:23 -08:00
|
|
|
if (!net_info) /* error message has already been handled */
|
2012-07-02 02:24:02 -07:00
|
|
|
{
|
|
|
|
svr->delete_me = EINA_TRUE;
|
|
|
|
goto error;
|
|
|
|
}
|
2013-03-09 22:49:54 -08:00
|
|
|
#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,
|
2013-12-19 21:07:50 -08:00
|
|
|
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;
|
2013-03-09 22:49:54 -08:00
|
|
|
}
|
|
|
|
#endif
|
2010-07-26 23:30:27 -07:00
|
|
|
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
|
|
|
|
net_info->info.ai_protocol);
|
2015-01-30 02:04:19 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (svr->fd == INVALID_SOCKET) goto error;
|
|
|
|
|
|
|
|
if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
|
|
|
|
#else
|
2011-12-09 21:09:47 -08:00
|
|
|
if (svr->fd < 0) goto error;
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2015-01-30 02:04:19 -08:00
|
|
|
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
|
|
|
|
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
|
|
|
|
#endif
|
|
|
|
|
2008-10-09 05:30:19 -07:00
|
|
|
if (type == ECORE_CON_REMOTE_MCAST)
|
|
|
|
{
|
2010-07-26 23:30:27 -07:00
|
|
|
if (net_info->info.ai_family == AF_INET)
|
|
|
|
{
|
|
|
|
if (!inet_pton(net_info->info.ai_family, net_info->ip,
|
|
|
|
&mreq.imr_multiaddr))
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
|
|
if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
2010-11-03 10:58:37 -07:00
|
|
|
(const void *)&mreq, sizeof(mreq)) != 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
}
|
2011-09-29 14:04:54 -07:00
|
|
|
#ifdef HAVE_IPV6
|
2010-07-26 23:30:27 -07:00
|
|
|
else if (net_info->info.ai_family == AF_INET6)
|
|
|
|
{
|
|
|
|
if (!inet_pton(net_info->info.ai_family, net_info->ip,
|
|
|
|
&mreq6.ipv6mr_multiaddr))
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
mreq6.ipv6mr_interface = htonl(INADDR_ANY);
|
2016-01-05 14:23:04 -08:00
|
|
|
if (setsockopt(svr->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
2010-11-03 10:58:37 -07:00
|
|
|
(const void *)&mreq6, sizeof(mreq6)) != 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
}
|
2011-09-29 14:04:54 -07:00
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
}
|
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2015-01-30 01:51:52 -08:00
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2013-03-09 22:49:54 -08:00
|
|
|
#ifdef HAVE_SYSTEMD
|
2013-12-19 21:07:50 -08:00
|
|
|
fd_ready:
|
2013-03-09 22:49:54 -08:00
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
svr->fd_handler =
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_svr_udp_handler, obj, NULL, NULL);
|
2010-07-26 23:30:27 -07:00
|
|
|
if (!svr->fd_handler)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:17:34 -08:00
|
|
|
memerr = "Memory allocation failure";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-16 13:32:50 -08:00
|
|
|
svr->ip = eina_stringshare_add(net_info->ip);
|
2008-10-09 05:30:19 -07:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2014-08-22 08:06:27 -07:00
|
|
|
if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
|
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
|
|
|
_ecore_con_server_kill(obj);
|
2008-10-09 05:30:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cb_tcp_connect(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Con_Info *net_info)
|
2008-10-06 02:41:39 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2010-07-26 23:30:27 -07:00
|
|
|
int res;
|
|
|
|
int curstate = 0;
|
2011-12-09 21:17:34 -08:00
|
|
|
const char *memerr = NULL;
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-10-06 02:41:39 -07:00
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
errno = 0;
|
2011-02-10 00:49:23 -08:00
|
|
|
if (!net_info) /* error message has already been handled */
|
2012-07-02 02:24:02 -07:00
|
|
|
{
|
|
|
|
svr->delete_me = EINA_TRUE;
|
|
|
|
goto error;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
|
|
|
|
net_info->info.ai_protocol);
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd == INVALID_SOCKET) goto error;
|
|
|
|
|
2015-01-30 01:51:52 -08:00
|
|
|
if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
|
|
|
|
#else
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd < 0) goto error;
|
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
|
|
|
|
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
|
2015-01-30 01:51:52 -08:00
|
|
|
#endif
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-07-30 10:03:34 -07:00
|
|
|
if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
|
2009-11-20 02:58:19 -08:00
|
|
|
{
|
2010-07-26 23:30:27 -07:00
|
|
|
int flag = 1;
|
2009-11-20 02:58:19 -08:00
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0)
|
|
|
|
{
|
|
|
|
goto error;
|
|
|
|
}
|
2009-11-20 02:58:19 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
res = connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen);
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (res == SOCKET_ERROR)
|
|
|
|
{
|
2015-01-30 01:51:52 -08:00
|
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK)
|
2011-12-09 21:09:47 -08:00
|
|
|
{
|
|
|
|
char *err;
|
|
|
|
err = evil_format_message(WSAGetLastError());
|
2014-08-26 03:07:43 -07:00
|
|
|
_ecore_con_event_server_error(obj, err, EINA_FALSE);
|
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
|
|
|
_ecore_con_server_kill(obj);
|
2011-12-09 21:09:47 -08:00
|
|
|
return;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#else
|
|
|
|
if (res < 0)
|
2008-10-06 02:41:39 -07:00
|
|
|
{
|
2011-12-09 21:09:47 -08:00
|
|
|
if (errno != EINPROGRESS) goto error;
|
2010-02-20 10:01:50 -08:00
|
|
|
#endif
|
2010-09-17 23:30:13 -07:00
|
|
|
svr->connecting = EINA_TRUE;
|
2010-07-26 23:30:27 -07:00
|
|
|
svr->fd_handler =
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_cl_handler, obj, NULL, NULL);
|
2008-10-06 02:41:39 -07:00
|
|
|
}
|
|
|
|
else
|
2014-10-08 02:53:15 -07:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2008-10-30 08:26:11 -07:00
|
|
|
|
2010-10-15 00:42:29 -07:00
|
|
|
if (svr->type & ECORE_CON_SSL)
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
|
|
|
svr->handshaking = EINA_TRUE;
|
|
|
|
svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
|
2011-12-05 20:48:55 -08:00
|
|
|
DBG("%s ssl handshake", svr->ecs_state ? "Queuing" : "Beginning");
|
2014-08-22 08:06:27 -07:00
|
|
|
if ((!svr->ecs_state) && ecore_con_ssl_server_init(obj))
|
2010-09-23 21:15:42 -07:00
|
|
|
goto error;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
if (!svr->fd_handler)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:17:34 -08:00
|
|
|
memerr = "Memory allocation failure";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2008-10-06 02:41:39 -07:00
|
|
|
|
2011-12-09 21:17:34 -08:00
|
|
|
if ((!svr->ecs) || (svr->ecs->lookup))
|
2011-12-05 19:32:16 -08:00
|
|
|
svr->ip = eina_stringshare_add(net_info->ip);
|
2008-10-08 17:46:29 -07:00
|
|
|
|
2008-10-06 02:41:39 -07:00
|
|
|
return;
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
memerr ? : errno ? strerror(errno) : "DNS error");
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
|
|
|
_ecore_con_server_kill(obj);
|
2008-10-06 02:41:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cb_udp_connect(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Con_Info *net_info)
|
2008-10-06 02:41:39 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2010-07-26 23:30:27 -07:00
|
|
|
int curstate = 0;
|
|
|
|
int broadcast = 1;
|
2011-12-09 21:17:34 -08:00
|
|
|
const char *memerr = NULL;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-10-06 02:41:39 -07:00
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
errno = 0;
|
2011-02-10 00:49:23 -08:00
|
|
|
if (!net_info) /* error message has already been handled */
|
2012-07-02 02:24:02 -07:00
|
|
|
{
|
|
|
|
svr->delete_me = EINA_TRUE;
|
|
|
|
goto error;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
|
|
|
|
net_info->info.ai_protocol);
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd == INVALID_SOCKET) goto error;
|
|
|
|
|
2015-01-30 01:51:52 -08:00
|
|
|
if (ioctlsocket(svr->fd, FIONBIO, &mode)) goto error;
|
|
|
|
#else
|
2015-01-30 02:04:19 -08:00
|
|
|
if (svr->fd < 0) goto error;
|
|
|
|
|
2011-12-09 21:09:47 -08:00
|
|
|
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
|
|
|
|
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
|
2015-01-30 01:51:52 -08:00
|
|
|
#endif
|
2010-07-30 10:03:34 -07:00
|
|
|
if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_BROADCAST)
|
2009-08-12 04:24:33 -07:00
|
|
|
{
|
2010-07-26 23:30:27 -07:00
|
|
|
if (setsockopt(svr->fd, SOL_SOCKET, SO_BROADCAST,
|
|
|
|
(const void *)&broadcast,
|
|
|
|
sizeof(broadcast)) < 0)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
|
|
|
goto error;
|
|
|
|
}
|
2009-08-12 04:24:33 -07:00
|
|
|
}
|
2011-12-09 21:17:34 -08:00
|
|
|
if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR,
|
|
|
|
(const void *)&curstate, sizeof(curstate)) < 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-17 23:06:05 -07:00
|
|
|
if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
|
2011-12-09 21:09:47 -08:00
|
|
|
goto error;
|
2010-09-17 23:06:05 -07:00
|
|
|
|
|
|
|
svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_cl_udp_handler, obj, NULL, NULL);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
if (!svr->fd_handler)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:17:34 -08:00
|
|
|
memerr = "Memory allocation failure";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2009-08-12 04:24:33 -07:00
|
|
|
|
2011-12-09 21:17:34 -08:00
|
|
|
if ((!svr->ecs) || (svr->ecs->lookup))
|
2011-12-05 19:32:16 -08:00
|
|
|
svr->ip = eina_stringshare_add(net_info->ip);
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2008-10-06 02:41:39 -07:00
|
|
|
return;
|
|
|
|
|
2010-07-26 23:30:27 -07:00
|
|
|
error:
|
2014-08-22 08:06:27 -07:00
|
|
|
if (errno || memerr) ecore_con_event_server_error(obj, memerr ? : strerror(errno));
|
|
|
|
ecore_con_ssl_server_shutdown(obj);
|
|
|
|
_ecore_con_server_kill(obj);
|
2008-10-06 02:41:39 -07:00
|
|
|
}
|
|
|
|
|
2008-10-01 08:27:52 -07:00
|
|
|
static Ecore_Con_State
|
2014-08-22 08:06:27 -07:00
|
|
|
svr_try_connect_plain(Ecore_Con_Server *obj)
|
2004-04-03 07:03:33 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2010-07-26 23:30:27 -07:00
|
|
|
int res;
|
|
|
|
int so_err = 0;
|
2011-03-03 13:05:28 -08:00
|
|
|
socklen_t size = sizeof(int);
|
2004-04-03 07:03:33 -08:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
res = getsockopt(svr->fd, SOL_SOCKET, SO_ERROR, (void *)&so_err, &size);
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (res == SOCKET_ERROR)
|
2010-11-17 01:31:15 -08:00
|
|
|
so_err = WSAGetLastError();
|
2010-02-20 10:01:50 -08:00
|
|
|
|
2011-12-21 02:02:30 -08:00
|
|
|
if ((so_err == WSAEINPROGRESS) && !svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CON_INPROGRESS;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#else
|
|
|
|
if (res < 0)
|
2010-11-17 01:31:15 -08:00
|
|
|
so_err = errno;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2011-12-21 02:02:30 -08:00
|
|
|
if ((so_err == EINPROGRESS) && !svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CON_INPROGRESS;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#endif
|
2008-10-01 08:27:52 -07:00
|
|
|
|
2010-11-17 01:31:15 -08:00
|
|
|
if (so_err)
|
2004-04-14 01:51:19 -07:00
|
|
|
{
|
2010-07-26 23:30:27 -07:00
|
|
|
/* we lost our server! */
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(obj, strerror(so_err));
|
2016-06-13 01:31:51 -07:00
|
|
|
DBG("Connection lost: %s", strerror(so_err));
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(obj);
|
2010-11-17 01:31:15 -08:00
|
|
|
return ECORE_CON_DISCONNECTED;
|
2004-04-14 01:51:19 -07:00
|
|
|
}
|
2010-09-17 23:06:05 -07:00
|
|
|
|
2010-09-23 22:57:03 -07:00
|
|
|
if ((!svr->delete_me) && (!svr->handshaking) && svr->connecting)
|
2004-04-14 01:51:19 -07:00
|
|
|
{
|
2013-12-19 21:07:50 -08:00
|
|
|
if (svr->ecs)
|
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
if (ecore_con_socks_svr_init(obj))
|
2013-12-19 21:07:50 -08:00
|
|
|
return ECORE_CON_INPROGRESS;
|
|
|
|
}
|
|
|
|
else
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_add(obj);
|
2004-04-14 01:51:19 -07:00
|
|
|
}
|
2008-10-01 08:27:52 -07:00
|
|
|
|
2013-03-14 04:48:05 -07:00
|
|
|
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);
|
|
|
|
}
|
2010-09-17 23:06:05 -07:00
|
|
|
|
2011-12-21 02:02:30 -08:00
|
|
|
if (!svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CON_CONNECTED;
|
2008-10-01 08:27:52 -07:00
|
|
|
else
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CON_DISCONNECTED;
|
2004-04-03 07:03:33 -08:00
|
|
|
}
|
|
|
|
|
2010-11-16 13:32:50 -08:00
|
|
|
static const char *
|
2011-09-29 14:05:20 -07:00
|
|
|
_ecore_con_pretty_ip(struct sockaddr *client_addr)
|
2010-01-31 03:58:37 -08:00
|
|
|
{
|
2011-09-29 14:04:54 -07:00
|
|
|
#ifndef HAVE_IPV6
|
|
|
|
char ipbuf[INET_ADDRSTRLEN + 1];
|
|
|
|
#else
|
2010-01-31 03:58:37 -08:00
|
|
|
char ipbuf[INET6_ADDRSTRLEN + 1];
|
2011-09-29 14:05:20 -07:00
|
|
|
#endif
|
|
|
|
int family = client_addr->sa_family;
|
|
|
|
void *src;
|
2010-01-31 03:58:37 -08:00
|
|
|
|
2013-12-19 21:07:50 -08:00
|
|
|
switch (family)
|
2010-01-31 03:58:37 -08:00
|
|
|
{
|
2013-12-19 21:07:50 -08:00
|
|
|
case AF_INET:
|
|
|
|
src = &(((struct sockaddr_in *)client_addr)->sin_addr);
|
|
|
|
break;
|
|
|
|
|
2011-09-29 14:05:20 -07:00
|
|
|
#ifdef HAVE_IPV6
|
2013-12-19 21:07:50 -08:00
|
|
|
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;
|
|
|
|
|
2011-09-29 14:04:54 -07:00
|
|
|
#endif
|
2013-12-19 21:07:50 -08:00
|
|
|
default:
|
|
|
|
return eina_stringshare_add("0.0.0.0");
|
|
|
|
}
|
2010-01-31 03:58:37 -08:00
|
|
|
|
2011-09-29 14:05:20 -07:00
|
|
|
if (!inet_ntop(family, src, ipbuf, sizeof(ipbuf)))
|
2010-11-16 13:32:50 -08:00
|
|
|
return eina_stringshare_add("0.0.0.0");
|
2010-01-31 03:58:37 -08:00
|
|
|
|
2011-02-10 00:49:23 -08:00
|
|
|
ipbuf[sizeof(ipbuf) - 1] = 0;
|
2010-11-16 13:32:50 -08:00
|
|
|
return eina_stringshare_add(ipbuf);
|
2010-01-31 03:58:37 -08:00
|
|
|
}
|
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_svr_tcp_handler(void *data,
|
2012-11-25 01:55:32 -08:00
|
|
|
Ecore_Fd_Handler *fd_handler EINA_UNUSED)
|
2008-10-30 08:26:11 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *svr_obj = data;
|
2014-08-22 05:14:59 -07:00
|
|
|
Ecore_Con_Client *obj = NULL;
|
2010-11-16 13:32:50 -08:00
|
|
|
unsigned char client_addr[256];
|
2011-04-29 00:34:12 -07:00
|
|
|
unsigned int client_addr_len;
|
2011-12-09 21:25:30 -08:00
|
|
|
const char *clerr = NULL;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(svr_obj, EFL_NETWORK_SERVER_CLASS);
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-10-30 08:26:11 -07:00
|
|
|
|
2011-12-21 02:02:30 -08:00
|
|
|
if (svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-17 23:06:05 -07:00
|
|
|
if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
|
2010-09-20 12:31:11 -07:00
|
|
|
(svr->client_count >= (unsigned int)svr->client_limit))
|
2010-09-17 23:06:05 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2008-10-30 08:26:11 -07:00
|
|
|
/* a new client */
|
2011-04-29 00:22:53 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_add(EFL_NETWORK_CLIENT_CLASS, NULL);
|
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2011-04-29 00:22:53 -07:00
|
|
|
if (!cl)
|
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(svr_obj, "Memory allocation failure when attempting to add a new client");
|
2011-04-29 00:22:53 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2014-08-22 08:06:27 -07:00
|
|
|
cl->host_server = svr_obj;
|
2011-04-29 00:22:53 -07:00
|
|
|
|
2011-04-29 00:34:12 -07:00
|
|
|
client_addr_len = sizeof(client_addr);
|
2010-11-16 13:32:50 -08:00
|
|
|
memset(&client_addr, 0, client_addr_len);
|
2011-04-29 00:22:53 -07:00
|
|
|
cl->fd = accept(svr->fd, (struct sockaddr *)&client_addr, (socklen_t *)&client_addr_len);
|
2015-01-30 02:04:19 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (cl->fd == INVALID_SOCKET) goto error;
|
|
|
|
#else
|
2011-12-09 21:25:30 -08:00
|
|
|
if (cl->fd < 0) goto error;
|
2015-01-30 02:04:19 -08:00
|
|
|
#endif
|
2010-09-17 23:06:05 -07:00
|
|
|
if ((svr->client_limit >= 0) && (svr->reject_excess_clients) &&
|
2010-09-20 12:31:11 -07:00
|
|
|
(svr->client_count >= (unsigned int)svr->client_limit))
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:25:30 -08:00
|
|
|
clerr = "Maximum client limit reached";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2015-01-30 01:51:52 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (ioctlsocket(cl->fd, FIONBIO, &mode)) goto error;
|
|
|
|
#else
|
2011-12-09 21:25:30 -08:00
|
|
|
if (fcntl(cl->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
|
|
|
|
if (fcntl(cl->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
|
2015-01-30 01:51:52 -08:00
|
|
|
#endif
|
2010-10-13 09:40:52 -07:00
|
|
|
cl->fd_handler = ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_svr_cl_handler, obj, NULL, NULL);
|
2011-12-09 21:25:30 -08:00
|
|
|
if (!cl->fd_handler) goto error;
|
2010-10-13 09:40:52 -07:00
|
|
|
|
2011-06-15 11:58:34 -07:00
|
|
|
if ((!svr->upgrade) && (svr->type & ECORE_CON_SSL))
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
|
|
|
cl->handshaking = EINA_TRUE;
|
|
|
|
cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
|
2014-08-22 05:14:59 -07:00
|
|
|
if (ecore_con_ssl_client_init(obj))
|
2011-12-09 21:25:30 -08:00
|
|
|
goto error;
|
2010-09-23 21:15:42 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-16 13:32:50 -08:00
|
|
|
cl->client_addr = malloc(client_addr_len);
|
|
|
|
if (!cl->client_addr)
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2011-12-09 21:25:30 -08:00
|
|
|
clerr = "Memory allocation failure when attempting to add a new client";
|
|
|
|
goto error;
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2010-11-16 13:32:50 -08:00
|
|
|
cl->client_addr_len = client_addr_len;
|
|
|
|
memcpy(cl->client_addr, &client_addr, client_addr_len);
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
svr->clients = eina_list_append(svr->clients, obj);
|
2010-09-20 12:31:11 -07:00
|
|
|
svr->client_count++;
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-09-23 21:15:42 -07:00
|
|
|
if ((!cl->delete_me) && (!cl->handshaking))
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_add(obj);
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-17 23:06:05 -07:00
|
|
|
|
2011-12-09 21:25:30 -08:00
|
|
|
error:
|
|
|
|
if (cl->fd_handler) ecore_main_fd_handler_del(cl->fd_handler);
|
|
|
|
if (cl->fd >= 0) close(cl->fd);
|
2012-09-06 00:34:00 -07:00
|
|
|
{
|
|
|
|
Ecore_Event *ev;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(cl->event_count, ev)
|
|
|
|
{
|
|
|
|
svr->event_count = eina_list_remove(svr->event_count, ev);
|
|
|
|
ecore_event_del(ev);
|
|
|
|
}
|
|
|
|
}
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_del(obj);
|
2014-08-22 08:06:27 -07:00
|
|
|
if (clerr || errno) ecore_con_event_server_error(svr_obj, clerr ? : strerror(errno));
|
2010-09-17 23:06:05 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2008-10-30 08:26:11 -07:00
|
|
|
}
|
2004-04-03 07:03:33 -08:00
|
|
|
|
2010-09-17 23:06:05 -07:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_cl_read(Ecore_Con_Server *obj)
|
2010-09-17 23:06:05 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-12-09 23:34:45 -08:00
|
|
|
int num = 0;
|
2011-12-09 14:35:12 -08:00
|
|
|
Eina_Bool lost_server = EINA_TRUE;
|
2011-12-09 23:34:45 -08:00
|
|
|
unsigned char buf[READBUFSIZ];
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
DBG("svr=%p", svr);
|
|
|
|
|
2010-10-02 14:13:56 -07:00
|
|
|
/* only possible with non-ssl connections */
|
2014-08-22 08:06:27 -07:00
|
|
|
if (svr->connecting && (svr_try_connect_plain(obj) != ECORE_CON_CONNECTED))
|
2013-12-19 21:07:50 -08:00
|
|
|
return;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
if (svr->handshaking && (!svr->ecs_state))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-11-03 12:08:31 -07:00
|
|
|
DBG("Continuing ssl handshake");
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!ecore_con_ssl_server_init(obj))
|
2013-12-19 21:07:50 -08:00
|
|
|
lost_server = EINA_FALSE;
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_timer_update(obj);
|
2010-11-03 12:08:31 -07:00
|
|
|
}
|
2011-12-09 23:34:45 -08:00
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
if (svr->ecs_state || !(svr->type & ECORE_CON_SSL))
|
2010-11-03 12:08:31 -07:00
|
|
|
{
|
2011-12-09 23:34:45 -08:00
|
|
|
errno = 0;
|
2015-01-30 05:01:50 -08:00
|
|
|
num = recv(svr->fd, (char *)buf, sizeof(buf), 0);
|
|
|
|
|
2010-12-17 00:44:53 -08:00
|
|
|
/* 0 is not a valid return value for a tcp socket */
|
2015-01-30 05:30:22 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if ((num > 0) || ((num < 0) && (WSAGetLastError() == WSAEWOULDBLOCK)))
|
|
|
|
#else
|
2011-12-09 23:34:45 -08:00
|
|
|
if ((num > 0) || ((num < 0) && (errno == EAGAIN)))
|
2015-01-30 05:30:22 -08:00
|
|
|
#endif
|
2013-12-19 21:07:50 -08:00
|
|
|
lost_server = EINA_FALSE;
|
2011-12-09 23:34:45 -08:00
|
|
|
else if (num < 0)
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(obj, strerror(errno));
|
2010-11-03 12:08:31 -07:00
|
|
|
}
|
2010-11-03 12:38:00 -07:00
|
|
|
else
|
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
num = ecore_con_ssl_server_read(obj, buf, sizeof(buf));
|
2010-12-17 01:02:44 -08:00
|
|
|
/* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
|
2011-12-09 23:34:45 -08:00
|
|
|
if (num >= 0)
|
2013-12-19 21:07:50 -08:00
|
|
|
lost_server = EINA_FALSE;
|
2010-11-03 12:38:00 -07:00
|
|
|
}
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2010-12-15 23:43:48 -08:00
|
|
|
if ((!svr->delete_me) && (num > 0))
|
2011-12-05 19:32:16 -08:00
|
|
|
{
|
|
|
|
if (svr->ecs_state)
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_socks_read(obj, buf, num);
|
2011-12-05 19:32:16 -08:00
|
|
|
else
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_data(obj, buf, num, EINA_TRUE);
|
2011-12-05 19:32:16 -08:00
|
|
|
}
|
2004-03-31 08:47:45 -08:00
|
|
|
|
2011-12-09 23:34:45 -08:00
|
|
|
if (lost_server)
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(obj);
|
2010-09-17 23:06:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cl_handler(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Fd_Handler *fd_handler)
|
2010-09-17 23:06:05 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2010-09-29 16:53:00 -07:00
|
|
|
Eina_Bool want_read, want_write;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2010-09-17 23:06:05 -07:00
|
|
|
|
2011-12-21 02:02:30 -08:00
|
|
|
if (svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-17 23:06:05 -07:00
|
|
|
|
|
|
|
if (svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-17 23:06:05 -07:00
|
|
|
|
2010-09-29 16:53:00 -07:00
|
|
|
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);
|
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
if ((!svr->ecs_state) && svr->handshaking && (want_read || want_write))
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
2010-09-29 16:53:00 -07:00
|
|
|
DBG("Continuing ssl handshake: preparing to %s...", want_read ? "read" : "write");
|
2010-11-03 09:11:12 -07:00
|
|
|
#ifdef ISCOMFITOR
|
2010-11-03 10:58:37 -07:00
|
|
|
if (want_read)
|
|
|
|
{
|
2010-11-03 12:08:31 -07:00
|
|
|
char buf[READBUFSIZ];
|
2010-11-03 10:58:37 -07:00
|
|
|
ssize_t len;
|
2015-01-30 05:01:50 -08:00
|
|
|
len = recv(svr->fd, (char *)buf, sizeof(buf), MSG_DONTWAIT | MSG_PEEK);
|
2010-11-03 10:58:37 -07:00
|
|
|
DBG("%zu bytes in buffer", len);
|
|
|
|
}
|
2010-09-29 07:52:36 -07:00
|
|
|
#endif
|
2014-08-22 08:06:27 -07:00
|
|
|
if (ecore_con_ssl_server_init(obj))
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
2016-06-13 01:31:51 -07:00
|
|
|
DBG("ssl handshaking failed!");
|
2010-10-28 03:59:30 -07:00
|
|
|
svr->handshaking = EINA_FALSE;
|
2010-09-23 22:57:03 -07:00
|
|
|
}
|
2010-10-01 18:32:54 -07:00
|
|
|
else if (!svr->ssl_state)
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_add(obj);
|
2011-12-05 19:32:16 -08:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2012-02-14 21:53:50 -08:00
|
|
|
if (svr->ecs && svr->ecs_state && (svr->ecs_state < ECORE_CON_PROXY_STATE_READ) && (!svr->ecs_buf))
|
2011-12-05 19:32:16 -08:00
|
|
|
{
|
2012-02-14 21:53:50 -08:00
|
|
|
if (svr->ecs_state < ECORE_CON_PROXY_STATE_INIT)
|
2010-09-23 22:57:03 -07:00
|
|
|
{
|
2011-12-05 19:32:16 -08:00
|
|
|
INF("PROXY STATE++");
|
|
|
|
svr->ecs_state++;
|
2010-09-23 21:15:42 -07:00
|
|
|
}
|
2014-08-22 08:06:27 -07:00
|
|
|
if (ecore_con_socks_svr_init(obj)) return ECORE_CALLBACK_RENEW;
|
2010-09-23 21:15:42 -07:00
|
|
|
}
|
2011-12-05 19:32:16 -08:00
|
|
|
if (want_read)
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_cl_read(obj);
|
2010-11-03 10:58:37 -07:00
|
|
|
else if (want_write) /* only possible with non-ssl connections */
|
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
if (svr->connecting && (!svr_try_connect_plain(obj)) && (!svr->ecs_state))
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_flush(obj);
|
2004-04-14 01:51:19 -07:00
|
|
|
}
|
2004-04-03 07:03:33 -08:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_cl_udp_handler(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Fd_Handler *fd_handler)
|
2008-09-25 03:14:31 -07:00
|
|
|
{
|
2010-11-03 12:08:31 -07:00
|
|
|
unsigned char buf[READBUFSIZ];
|
|
|
|
int num;
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2010-11-03 12:08:31 -07:00
|
|
|
Eina_Bool want_read, want_write;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2010-11-03 12:08:31 -07:00
|
|
|
|
|
|
|
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);
|
2008-09-25 03:14:31 -07:00
|
|
|
|
2012-10-04 07:56:22 -07:00
|
|
|
if (svr->delete_me || ((!want_read) && (!want_write)))
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 12:08:31 -07:00
|
|
|
if (want_write)
|
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_flush(obj);
|
2010-11-03 12:08:31 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
2015-01-30 05:01:50 -08:00
|
|
|
num = recv(svr->fd, (char *)buf, READBUFSIZ, 0);
|
2010-11-03 12:08:31 -07:00
|
|
|
|
2010-12-17 00:15:52 -08:00
|
|
|
if ((!svr->delete_me) && (num > 0))
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_data(obj, buf, num, EINA_TRUE);
|
2010-11-03 12:08:31 -07:00
|
|
|
|
2010-12-16 05:16:40 -08:00
|
|
|
if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
|
2011-02-10 00:49:23 -08:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(obj, strerror(errno));
|
|
|
|
_ecore_con_server_kill(obj);
|
2011-02-10 00:49:23 -08:00
|
|
|
}
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2008-09-25 03:14:31 -07:00
|
|
|
}
|
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_svr_udp_handler(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Fd_Handler *fd_handler)
|
2008-09-17 08:08:48 -07:00
|
|
|
{
|
2010-11-03 12:08:31 -07:00
|
|
|
unsigned char buf[READBUFSIZ];
|
|
|
|
unsigned char client_addr[256];
|
2011-03-03 13:05:28 -08:00
|
|
|
socklen_t client_addr_len = sizeof(client_addr);
|
2010-11-03 12:08:31 -07:00
|
|
|
int num;
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *svr_obj = data;
|
2014-08-22 05:14:59 -07:00
|
|
|
Ecore_Con_Client *obj = NULL;
|
2015-01-30 05:11:56 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
u_long mode = 1;
|
|
|
|
#endif
|
2008-09-17 08:08:48 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(svr_obj, EFL_NETWORK_SERVER_CLASS);
|
2011-12-21 02:02:30 -08:00
|
|
|
if (svr->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-11-03 12:08:31 -07:00
|
|
|
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
|
2013-08-05 04:39:19 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2008-09-17 08:08:48 -07:00
|
|
|
|
2010-11-03 12:08:31 -07:00
|
|
|
if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#ifdef _WIN32
|
2015-01-30 01:51:52 -08:00
|
|
|
if (!ioctlsocket(svr->fd, FIONBIO, &mode))
|
2011-03-03 13:05:28 -08:00
|
|
|
num = recvfrom(svr->fd, (char *)buf, sizeof(buf), 0,
|
2013-12-19 21:07:50 -08:00
|
|
|
(struct sockaddr *)&client_addr,
|
|
|
|
&client_addr_len);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-02-20 10:01:50 -08:00
|
|
|
#else
|
2010-11-03 12:08:31 -07:00
|
|
|
num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT,
|
2013-12-19 21:07:50 -08:00
|
|
|
(struct sockaddr *)&client_addr,
|
|
|
|
&client_addr_len);
|
2010-02-20 10:01:50 -08:00
|
|
|
#endif
|
2008-10-09 05:30:19 -07:00
|
|
|
|
2010-12-16 05:16:40 -08:00
|
|
|
if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
|
2010-11-03 12:08:31 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
ecore_con_event_server_error(svr_obj, strerror(errno));
|
2010-11-03 12:08:31 -07:00
|
|
|
if (!svr->delete_me)
|
2011-11-10 18:44:16 -08:00
|
|
|
ecore_con_event_client_del(NULL);
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_kill(svr_obj);
|
2010-11-03 12:08:31 -07:00
|
|
|
return ECORE_CALLBACK_CANCEL;
|
2008-09-17 08:08:48 -07:00
|
|
|
}
|
2010-11-03 12:08:31 -07:00
|
|
|
|
|
|
|
/* Create a new client for use in the client data event */
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_add(EFL_NETWORK_CLIENT_CLASS, NULL);
|
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2010-11-03 12:08:31 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cl, ECORE_CALLBACK_RENEW);
|
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
cl->host_server = svr_obj;
|
2015-11-20 08:46:38 -08:00
|
|
|
cl->fd = -1;
|
2010-11-16 13:32:50 -08:00
|
|
|
cl->client_addr = malloc(client_addr_len);
|
2010-11-05 18:22:50 -07:00
|
|
|
if (!cl->client_addr)
|
2010-11-03 12:08:31 -07:00
|
|
|
{
|
|
|
|
free(cl);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
cl->client_addr_len = client_addr_len;
|
|
|
|
|
|
|
|
memcpy(cl->client_addr, &client_addr, client_addr_len);
|
2014-08-22 05:14:59 -07:00
|
|
|
svr->clients = eina_list_append(svr->clients, obj);
|
2010-11-03 12:08:31 -07:00
|
|
|
svr->client_count++;
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_add(obj);
|
|
|
|
ecore_con_event_client_data(obj, buf, num, EINA_TRUE);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2008-09-17 08:08:48 -07:00
|
|
|
}
|
|
|
|
|
2010-09-17 22:30:16 -07:00
|
|
|
static void
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_svr_cl_read(Ecore_Con_Client *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2010-11-03 12:08:31 -07:00
|
|
|
int num = 0;
|
|
|
|
Eina_Bool lost_client = EINA_TRUE;
|
|
|
|
unsigned char buf[READBUFSIZ];
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2011-05-14 10:52:30 -07:00
|
|
|
DBG("cl=%p", cl);
|
|
|
|
|
2010-11-03 12:08:31 -07:00
|
|
|
if (cl->handshaking)
|
2010-09-17 22:30:16 -07:00
|
|
|
{
|
2010-11-03 12:08:31 -07:00
|
|
|
/* add an extra handshake attempt just before read, even though
|
|
|
|
* read also attempts to handshake, to try to finish sooner
|
|
|
|
*/
|
2014-08-22 05:14:59 -07:00
|
|
|
if (ecore_con_ssl_client_init(obj))
|
2010-11-03 12:08:31 -07:00
|
|
|
lost_client = EINA_FALSE;
|
2010-09-24 21:22:10 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
2010-11-03 12:08:31 -07:00
|
|
|
}
|
2010-09-24 20:02:10 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!(host_server->type & ECORE_CON_SSL) && (!cl->upgrade))
|
2010-11-03 12:08:31 -07:00
|
|
|
{
|
2015-01-30 05:01:50 -08:00
|
|
|
num = recv(cl->fd, (char *)buf, sizeof(buf), 0);
|
|
|
|
|
2010-12-17 00:44:53 -08:00
|
|
|
/* 0 is not a valid return value for a tcp socket */
|
2010-12-17 04:09:14 -08:00
|
|
|
if ((num > 0) || ((num < 0) && ((errno == EAGAIN) || (errno == EINTR))))
|
2010-11-03 10:58:37 -07:00
|
|
|
lost_client = EINA_FALSE;
|
2011-02-15 12:17:48 -08:00
|
|
|
else if (num < 0)
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_error(obj, strerror(errno));
|
2010-11-03 12:08:31 -07:00
|
|
|
}
|
2010-11-03 12:38:00 -07:00
|
|
|
else
|
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
num = ecore_con_ssl_client_read(obj, buf, sizeof(buf));
|
2010-12-17 01:02:44 -08:00
|
|
|
/* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
|
2010-12-15 23:43:48 -08:00
|
|
|
if (num >= 0)
|
2010-11-03 12:38:00 -07:00
|
|
|
lost_client = EINA_FALSE;
|
|
|
|
}
|
2010-09-17 22:30:16 -07:00
|
|
|
|
2010-12-15 23:43:48 -08:00
|
|
|
if ((!cl->delete_me) && (num > 0))
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_data(obj, buf, num, EINA_TRUE);
|
2010-12-15 23:43:48 -08:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
if (lost_client) _ecore_con_client_kill(obj);
|
2010-09-17 22:30:16 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-17 22:30:16 -07:00
|
|
|
static Eina_Bool
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_svr_cl_handler(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Fd_Handler *fd_handler)
|
2010-09-17 22:30:16 -07:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
Ecore_Con_Client *obj = data;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-17 22:30:16 -07:00
|
|
|
if (cl->delete_me)
|
2010-11-03 10:58:37 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-17 22:30:16 -07:00
|
|
|
|
2010-09-28 22:08:47 -07:00
|
|
|
if (cl->handshaking && ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ | ECORE_FD_WRITE))
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
if (ecore_con_ssl_client_init(obj))
|
2010-09-23 21:15:42 -07:00
|
|
|
{
|
2016-06-13 01:31:51 -07:00
|
|
|
DBG("ssl handshaking failed!");
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_kill(obj);
|
2011-12-09 21:42:32 -08:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-09-23 21:15:42 -07:00
|
|
|
}
|
2010-10-01 18:32:54 -07:00
|
|
|
else if (!cl->ssl_state)
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_add(obj);
|
2010-09-23 21:15:42 -07:00
|
|
|
}
|
2010-09-28 22:08:47 -07:00
|
|
|
else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_svr_cl_read(obj);
|
2010-09-22 01:03:38 -07:00
|
|
|
|
2010-09-17 22:30:16 -07:00
|
|
|
else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_flush(obj);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_server_flush(Ecore_Con_Server *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2014-04-04 03:35:16 -07:00
|
|
|
int count;
|
|
|
|
size_t num;
|
2013-02-08 00:35:27 -08:00
|
|
|
size_t buf_len;
|
2014-04-04 03:35:16 -07:00
|
|
|
size_t *buf_offset;
|
2012-10-09 01:27:38 -07:00
|
|
|
const unsigned char *buf;
|
2013-02-08 00:35:27 -08:00
|
|
|
Eina_Binbuf *buf_p;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
DBG("(svr=%p,buf=%p)", svr, svr->buf);
|
2013-03-14 04:48:05 -07:00
|
|
|
if (!svr->fd_handler) return;
|
2011-05-14 10:52:30 -07:00
|
|
|
#ifdef _WIN32
|
2014-08-26 03:07:43 -07:00
|
|
|
if (ecore_con_local_win32_server_flush(obj))
|
2011-05-14 10:52:30 -07:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2013-03-14 04:48:05 -07:00
|
|
|
if ((!svr->buf) && (!svr->ecs_buf))
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
|
|
|
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
|
|
|
|
return;
|
|
|
|
}
|
2004-04-02 10:32:55 -08:00
|
|
|
|
2013-02-08 00:35:27 -08:00
|
|
|
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;
|
2010-12-09 13:02:53 -08:00
|
|
|
|
2004-04-02 10:32:55 -08:00
|
|
|
/* check whether we need to write anything at all.
|
2008-10-09 05:30:19 -07:00
|
|
|
* we must not write zero bytes with SSL_write() since it
|
|
|
|
* causes undefined behaviour
|
|
|
|
*/
|
2010-12-09 13:02:53 -08:00
|
|
|
/* we thank Tommy[D] for needing to check negative buffer sizes
|
|
|
|
* here because his system is amazing.
|
|
|
|
*/
|
|
|
|
if (num <= 0) return;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
if ((!svr->ecs_state) && svr->handshaking)
|
2010-09-24 21:22:10 -07:00
|
|
|
{
|
2010-09-28 20:52:32 -07:00
|
|
|
DBG("Continuing ssl handshake");
|
2014-08-22 08:06:27 -07:00
|
|
|
if (ecore_con_ssl_server_init(obj))
|
|
|
|
_ecore_con_server_kill(obj);
|
|
|
|
_ecore_con_server_timer_update(obj);
|
2010-09-24 21:22:10 -07:00
|
|
|
return;
|
|
|
|
}
|
2010-09-24 20:02:10 -07:00
|
|
|
|
2011-12-05 20:48:55 -08:00
|
|
|
if (svr->ecs_state || (!(svr->type & ECORE_CON_SSL)))
|
2015-01-30 02:21:03 -08:00
|
|
|
count = send(svr->fd, (const char *)buf + *buf_offset, num, 0);
|
2008-10-30 08:26:11 -07:00
|
|
|
else
|
2014-08-22 08:06:27 -07:00
|
|
|
count = ecore_con_ssl_server_write(obj, buf + *buf_offset, num);
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2015-01-30 02:21:03 -08:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (count == SOCKET_ERROR)
|
2010-09-28 21:06:28 -07:00
|
|
|
{
|
2015-01-30 02:21:03 -08:00
|
|
|
switch (WSAGetLastError())
|
2013-12-19 21:07:50 -08:00
|
|
|
{
|
2015-01-30 02:21:03 -08:00
|
|
|
case WSAEINTR:
|
|
|
|
case WSAEINPROGRESS:
|
|
|
|
case WSAEWOULDBLOCK:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
LPTSTR s;
|
|
|
|
|
|
|
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
2015-01-30 05:09:34 -08:00
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL, WSAGetLastError(),
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPTSTR)&s, 0, NULL);
|
2015-01-30 05:11:56 -08:00
|
|
|
ecore_con_event_server_error(obj, (char *)s);
|
2015-01-30 02:21:03 -08:00
|
|
|
free(s);
|
2015-01-30 05:11:56 -08:00
|
|
|
_ecore_con_server_kill(obj);
|
2015-01-30 02:21:03 -08:00
|
|
|
}
|
2013-12-19 21:07:50 -08:00
|
|
|
}
|
2010-09-28 21:06:28 -07:00
|
|
|
}
|
2015-01-30 02:21:03 -08:00
|
|
|
#else
|
|
|
|
if (count < 0)
|
|
|
|
{
|
|
|
|
if ((errno != EAGAIN) && (errno != EINTR))
|
|
|
|
{
|
2015-01-30 05:11:56 -08:00
|
|
|
ecore_con_event_server_error(obj, strerror(errno));
|
|
|
|
_ecore_con_server_kill(obj);
|
2015-01-30 02:21:03 -08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-04-02 10:32:55 -08:00
|
|
|
|
2014-08-22 08:06:27 -07:00
|
|
|
if (count && (!svr->ecs_state)) ecore_con_event_server_write(obj, count);
|
2013-02-08 00:35:27 -08:00
|
|
|
|
|
|
|
if (!eina_binbuf_remove(buf_p, 0, count))
|
|
|
|
*buf_offset += count;
|
2011-12-05 19:32:16 -08:00
|
|
|
else
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2013-02-08 00:35:27 -08:00
|
|
|
*buf_offset = 0;
|
|
|
|
buf_len -= count;
|
|
|
|
}
|
|
|
|
if (*buf_offset >= buf_len)
|
|
|
|
{
|
|
|
|
*buf_offset = 0;
|
|
|
|
eina_binbuf_free(buf_p);
|
|
|
|
|
2011-12-05 19:32:16 -08:00
|
|
|
if (svr->ecs_buf)
|
|
|
|
{
|
|
|
|
svr->ecs_buf = NULL;
|
|
|
|
INF("PROXY STATE++");
|
|
|
|
svr->ecs_state++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
svr->buf = NULL;
|
2011-12-10 00:14:50 -08:00
|
|
|
#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
|
2011-12-05 19:32:16 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
if (svr->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2014-04-11 02:50:47 -07:00
|
|
|
else if (((unsigned int)count < num) && svr->fd_handler)
|
2010-11-04 08:01:05 -07:00
|
|
|
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_client_flush(Ecore_Con_Client *obj)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(obj, EFL_NETWORK_CLIENT_CLASS);
|
2014-04-04 03:35:16 -07:00
|
|
|
int count = 0;
|
|
|
|
size_t num = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2013-03-14 04:48:05 -07:00
|
|
|
if (!cl->fd_handler) return;
|
2011-05-14 10:52:30 -07:00
|
|
|
#ifdef _WIN32
|
2014-08-26 03:07:43 -07:00
|
|
|
if (ecore_con_local_win32_client_flush(obj))
|
2011-05-14 10:52:30 -07:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2013-03-14 04:48:05 -07:00
|
|
|
if (!cl->buf)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
|
|
|
ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
|
|
|
|
return;
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-24 21:22:10 -07:00
|
|
|
if (cl->handshaking)
|
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
if (ecore_con_ssl_client_init(obj))
|
2010-09-24 21:22:10 -07:00
|
|
|
count = -1;
|
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
_ecore_con_cl_timer_update(obj);
|
2010-09-24 21:22:10 -07:00
|
|
|
}
|
2010-09-24 20:02:10 -07:00
|
|
|
|
|
|
|
if (!count)
|
|
|
|
{
|
2012-07-16 03:30:31 -07:00
|
|
|
if (!cl->buf) return;
|
2011-07-16 06:07:39 -07:00
|
|
|
num = eina_binbuf_length_get(cl->buf) - cl->buf_offset;
|
2010-12-09 13:04:22 -08:00
|
|
|
if (num <= 0) return;
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
if (!(host_server->type & ECORE_CON_SSL) && (!cl->upgrade))
|
2015-01-30 05:11:56 -08:00
|
|
|
count = send(cl->fd, (char *)eina_binbuf_string_get(cl->buf) + cl->buf_offset, num, 0);
|
2010-09-24 20:02:10 -07:00
|
|
|
else
|
2014-08-22 05:14:59 -07:00
|
|
|
count = ecore_con_ssl_client_write(obj, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num);
|
2010-09-24 20:02:10 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2010-09-24 20:02:10 -07:00
|
|
|
if (count < 0)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-12-11 08:51:29 -08:00
|
|
|
if ((errno != EAGAIN) && (errno != EINTR) && (!cl->delete_me))
|
|
|
|
{
|
2014-08-22 05:14:59 -07:00
|
|
|
ecore_con_event_client_error(obj, strerror(errno));
|
|
|
|
_ecore_con_client_kill(obj);
|
2010-12-11 08:51:29 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
|
|
|
return;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2014-08-22 05:14:59 -07:00
|
|
|
if (count) ecore_con_event_client_write(obj, count);
|
2012-03-13 06:44:18 -07:00
|
|
|
cl->buf_offset += count, num -= count;
|
2011-07-16 06:07:39 -07:00
|
|
|
if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-07-26 23:30:27 -07:00
|
|
|
cl->buf_offset = 0;
|
2011-07-16 06:07:39 -07:00
|
|
|
eina_binbuf_free(cl->buf);
|
2010-07-26 23:30:27 -07:00
|
|
|
cl->buf = NULL;
|
2011-12-10 00:14:50 -08:00
|
|
|
#ifdef TCP_CORK
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2014-08-22 08:06:27 -07:00
|
|
|
if ((host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_CORK)
|
2011-12-10 00:14:50 -08:00
|
|
|
{
|
|
|
|
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
|
2010-07-26 23:30:27 -07:00
|
|
|
if (cl->fd_handler)
|
2010-11-03 10:58:37 -07:00
|
|
|
ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2014-04-11 02:26:18 -07:00
|
|
|
else if (cl->fd_handler)
|
2010-11-04 08:01:05 -07:00
|
|
|
ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-03-19 21:53:12 -08:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_client_add_free(Ecore_Con_Server *obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2006-03-19 21:53:12 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2006-03-19 21:53:12 -08:00
|
|
|
Ecore_Con_Event_Client_Add *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->client)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
|
2013-01-02 22:56:42 -08:00
|
|
|
Eina_Bool svrfreed = EINA_FALSE;
|
2013-12-19 21:07:50 -08:00
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if ((svr) && (cl))
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
cl->event_count = eina_list_remove(cl->event_count, e);
|
|
|
|
if (cl->host_server)
|
2013-01-02 22:56:42 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
2013-01-02 22:56:42 -08:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_client_add_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2006-03-19 21:53:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_client_del_free(Ecore_Con_Server *obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2006-03-19 21:53:12 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2006-03-19 21:53:12 -08:00
|
|
|
Ecore_Con_Event_Client_Del *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->client)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
|
2013-01-02 22:56:42 -08:00
|
|
|
Eina_Bool svrfreed = EINA_FALSE;
|
2013-12-19 21:07:50 -08:00
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if ((svr) && (cl))
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
cl->event_count = eina_list_remove(cl->event_count, e);
|
|
|
|
if (cl->host_server)
|
2013-01-02 22:56:42 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
2013-01-02 22:56:42 -08:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
}
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_client_del_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2006-03-19 21:53:12 -08:00
|
|
|
}
|
|
|
|
|
2011-09-13 16:03:26 -07:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_client_write_free(Ecore_Con_Server *obj,
|
2011-09-13 16:03:26 -07:00
|
|
|
Ecore_Con_Event_Client_Write *e)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->client)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
|
2013-01-02 22:56:42 -08:00
|
|
|
Eina_Bool svrfreed = EINA_FALSE;
|
2013-12-19 21:07:50 -08:00
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if ((svr) && (cl))
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
cl->event_count = eina_list_remove(cl->event_count, e);
|
|
|
|
if (cl->host_server)
|
2013-01-02 22:56:42 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
2013-01-02 22:56:42 -08:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
}
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_client_write_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2011-09-13 16:03:26 -07:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_client_data_free(Ecore_Con_Server *obj,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2003-09-23 01:09:32 -07:00
|
|
|
Ecore_Con_Event_Client_Data *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->client)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
|
2013-01-02 22:56:42 -08:00
|
|
|
Eina_Bool svrfreed = EINA_FALSE;
|
2013-12-19 21:07:50 -08:00
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if ((svr) && (cl))
|
2013-01-02 22:56:42 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
cl->event_count = eina_list_remove(cl->event_count, e);
|
|
|
|
if (cl->host_server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *host_server = efl_data_scope_get(cl->host_server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2013-01-02 22:56:42 -08:00
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
free(e->data);
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_client_data_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2006-03-19 21:53:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_con_event_server_add_free(void *data EINA_UNUSED,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2006-03-19 21:53:12 -08:00
|
|
|
{
|
|
|
|
Ecore_Con_Event_Server_Add *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_server_add_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2006-03-19 21:53:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_con_event_server_del_free(void *data EINA_UNUSED,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2006-03-19 21:53:12 -08:00
|
|
|
{
|
|
|
|
Ecore_Con_Event_Server_Del *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
if (svr)
|
|
|
|
{
|
|
|
|
svr->event_count = eina_list_remove(svr->event_count, ev);
|
|
|
|
if (!svr->event_count)
|
|
|
|
_ecore_con_server_free(e->server);
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_server_del_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2011-09-13 16:03:26 -07:00
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_con_event_server_write_free(void *data EINA_UNUSED,
|
2011-09-13 16:03:26 -07:00
|
|
|
Ecore_Con_Event_Server_Write *e)
|
|
|
|
{
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_server_write_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2011-09-13 16:03:26 -07:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_con_event_server_data_free(void *data EINA_UNUSED,
|
2013-12-19 21:07:50 -08:00
|
|
|
void *ev)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Con_Event_Server_Data *e;
|
|
|
|
|
|
|
|
e = ev;
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
2011-02-10 11:17:30 -08:00
|
|
|
|
2011-11-10 18:44:16 -08:00
|
|
|
free(e->data);
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_server_data_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_con_event_server_error_free(void *data EINA_UNUSED, Ecore_Con_Event_Server_Error *e)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->server)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(e->server, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
free(e->error);
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_server_error_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2011-02-10 11:17:30 -08:00
|
|
|
}
|
2010-07-26 23:30:27 -07:00
|
|
|
|
2011-02-10 11:17:30 -08:00
|
|
|
static void
|
2014-08-22 08:06:27 -07:00
|
|
|
_ecore_con_event_client_error_free(Ecore_Con_Server *obj, Ecore_Con_Event_Client_Error *e)
|
2011-02-10 11:17:30 -08:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2011-11-10 18:44:16 -08:00
|
|
|
if (e->client)
|
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Client_Data *cl = efl_data_scope_get(e->client, EFL_NETWORK_CLIENT_CLASS);
|
2013-01-02 22:56:42 -08:00
|
|
|
Eina_Bool svrfreed = EINA_FALSE;
|
2013-12-19 21:07:50 -08:00
|
|
|
|
2015-06-24 21:18:22 -07:00
|
|
|
if ((svr) && (cl))
|
2011-11-10 18:44:16 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
if (eina_list_data_find(svr->clients, e->client))
|
2013-01-02 22:56:42 -08:00
|
|
|
{
|
2015-06-24 21:18:22 -07:00
|
|
|
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);
|
2013-01-02 22:56:42 -08:00
|
|
|
}
|
|
|
|
}
|
2011-11-10 18:44:16 -08:00
|
|
|
}
|
|
|
|
free(e->error);
|
2011-11-06 04:26:00 -08:00
|
|
|
ecore_con_event_client_error_free(e);
|
2011-11-10 18:44:16 -08:00
|
|
|
_ecore_con_event_count--;
|
|
|
|
if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
|
|
|
|
ecore_con_mempool_shutdown();
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2010-07-22 04:32:55 -07:00
|
|
|
|
|
|
|
static void
|
2013-12-19 21:07:50 -08:00
|
|
|
_ecore_con_lookup_done(void *data,
|
2010-11-03 10:58:37 -07:00
|
|
|
Ecore_Con_Info *infos)
|
2010-07-22 04:32:55 -07:00
|
|
|
{
|
2014-08-22 08:06:27 -07:00
|
|
|
Ecore_Con_Server *obj = data;
|
2010-07-22 04:32:55 -07:00
|
|
|
Ecore_Con_Lookup *lk;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
Efl_Network_Server_Data *svr = efl_data_scope_get(obj, EFL_NETWORK_SERVER_CLASS);
|
2015-06-24 21:18:22 -07:00
|
|
|
if (!svr) return;
|
2010-07-22 04:32:55 -07:00
|
|
|
lk = svr->data;
|
|
|
|
|
|
|
|
if (infos)
|
2010-11-03 10:58:37 -07:00
|
|
|
lk->done_cb(infos->info.ai_canonname, infos->ip,
|
|
|
|
infos->info.ai_addr, infos->info.ai_addrlen,
|
|
|
|
(void *)lk->data);
|
2010-07-22 04:32:55 -07:00
|
|
|
else
|
2010-11-03 10:58:37 -07:00
|
|
|
lk->done_cb(NULL, NULL, NULL, 0, (void *)lk->data);
|
2010-07-22 04:32:55 -07:00
|
|
|
|
|
|
|
free(lk);
|
|
|
|
}
|
2010-11-03 10:58:37 -07:00
|
|
|
|
2016-05-11 05:00:57 -07:00
|
|
|
#include "efl_network.eo.c"
|
2016-02-12 12:02:01 -08:00
|
|
|
#include "efl_network_client.eo.c"
|
2016-02-04 23:09:53 -08:00
|
|
|
#include "efl_network_server.eo.c"
|
2016-01-04 12:35:37 -08:00
|
|
|
#include "efl_network_connector.eo.c"
|
efl.net: socket, server and dialer for TCP.
Efl.Net.Server defines how to accept new connections, doing the
bind(), listen() and accept() for protocols such as TCP.
Efl.Net.Dialer defines to to reach a server.
Both are based on Efl.Net.Socket as communication interface that is
based on Efl.Io.Reader, Efl.Io.Writer and Efl.Io.Closer, thus being
usable with code such as Efl.Io.Copier.
The Server will emit an event "client,add" with the established
Socket, which is a child and can be closed by both the server or the
user.
The Dialer extends the Socket and allows for creating one given an
address, that will be resolved and connected.
TCP is the initial implementation so we an validate the
interfaces. UDP, Unix-Local and SSL will come later as derivate
classes.
The examples are documented and should cover the basic principles:
- efl_io_copier_example can accept "tcp://IP:PORT" and will work as a
"netcat", can send data from socket, file or stdin to a socket,
file, stdout or stderr.
- efl_net_server_example listens for connections and can either reply
"Hello World!" and take some data or work as an echo-server,
looping back all received data to the user.
More complex interactions that require a "chat" between client and
server will be covered with new classes later, such as a queue that
empties itself once data is read.
2016-08-17 21:53:16 -07:00
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr)
|
|
|
|
{
|
|
|
|
char p[INET6_ADDRSTRLEN];
|
|
|
|
const void *mem;
|
|
|
|
unsigned short port;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (addr->sa_family == AF_INET)
|
|
|
|
{
|
|
|
|
const struct sockaddr_in *a = (const struct sockaddr_in *)addr;
|
|
|
|
mem = &a->sin_addr;
|
|
|
|
port = ntohs(a->sin_port);
|
|
|
|
}
|
|
|
|
else if (addr->sa_family == AF_INET6)
|
|
|
|
{
|
|
|
|
const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr;
|
|
|
|
mem = &a->sin6_addr;
|
|
|
|
port = ntohs(a->sin6_port);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("unsupported address family: %d", addr->sa_family);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!inet_ntop(addr->sa_family, mem, p, sizeof(p)))
|
|
|
|
{
|
|
|
|
ERR("inet_ntop(%d, %p, %p, %zd): %s",
|
|
|
|
addr->sa_family, mem, p, sizeof(p), strerror(errno));
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr->sa_family == AF_INET)
|
|
|
|
r = snprintf(buf, buflen, "%s:%hu", p, port);
|
|
|
|
else
|
|
|
|
r = snprintf(buf, buflen, "[%s]:%hu", p, port);
|
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
{
|
|
|
|
ERR("could not snprintf(): %s", strerror(errno));
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
else if (r > buflen)
|
|
|
|
{
|
|
|
|
ERR("buffer is too small: %d, required %d", buflen, r);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2016-08-24 08:34:59 -07:00
|
|
|
|
2016-09-09 16:09:51 -07:00
|
|
|
Eina_Bool
|
|
|
|
efl_net_ip_port_split(char *buf, const char **p_host, const char **p_port)
|
|
|
|
{
|
|
|
|
char *host, *port;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(p_host, EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(p_port, EINA_FALSE);
|
|
|
|
|
|
|
|
host = buf;
|
|
|
|
if (host[0] == '[')
|
|
|
|
{
|
|
|
|
/* IPv6 is: [IP]:port */
|
|
|
|
host++;
|
|
|
|
port = strchr(host, ']');
|
|
|
|
if (!port) return EINA_FALSE;
|
|
|
|
*port = '\0';
|
|
|
|
port++;
|
|
|
|
|
|
|
|
if (port[0] == ':')
|
|
|
|
port++;
|
|
|
|
else
|
|
|
|
port = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
port = strchr(host, ':');
|
|
|
|
if (port)
|
|
|
|
{
|
|
|
|
*port = '\0';
|
|
|
|
port++;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (*port == '\0') port = NULL;
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*p_host = host;
|
|
|
|
*p_port = port;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
static void
|
|
|
|
_cleanup_close(void *data)
|
|
|
|
{
|
|
|
|
int *p_fd = data;
|
|
|
|
int fd = *p_fd;
|
|
|
|
*p_fd = -1;
|
|
|
|
if (fd >= 0) close(fd);
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
2016-08-24 08:34:59 -07:00
|
|
|
int
|
|
|
|
efl_net_socket4(int domain, int type, int protocol, Eina_Bool close_on_exec)
|
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
int fd = -1;
|
2016-08-24 08:34:59 -07:00
|
|
|
|
|
|
|
#ifdef SOCK_CLOEXEC
|
|
|
|
if (close_on_exec) type |= SOCK_CLOEXEC;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
fd = socket(domain, type, protocol);
|
|
|
|
#ifndef SOCK_CLOEXEC
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
|
|
|
if (fd > 0)
|
2016-08-24 08:34:59 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (close_on_exec)
|
2016-08-24 08:34:59 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
|
|
|
|
{
|
|
|
|
int errno_bkp = errno;
|
|
|
|
ERR("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
|
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
|
|
|
errno = errno_bkp;
|
|
|
|
}
|
2016-08-24 08:34:59 -07:00
|
|
|
}
|
|
|
|
}
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_FALSE); /* we need fd on success */
|
2016-08-24 08:34:59 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
typedef struct _Efl_Net_Connect_Async_Data
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Connect_Async_Cb cb;
|
2016-09-09 16:09:51 -07:00
|
|
|
const void *data;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
socklen_t addrlen;
|
|
|
|
Eina_Bool close_on_exec;
|
|
|
|
int type;
|
|
|
|
int protocol;
|
|
|
|
int sockfd;
|
|
|
|
Eina_Error error;
|
|
|
|
struct sockaddr addr[];
|
|
|
|
} Efl_Net_Connect_Async_Data;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Connect_Async_Data *d = data;
|
|
|
|
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")] = "";
|
|
|
|
int r;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
eina/ecore: allow threads to be canceled, use in ecore_con.
As discussed in the mailing list, many people will use worker threads
to execute blocking syscalls and mandating ecore_thread_check() for
voluntary preemption reduces the ecore_thread usefulness a lot.
A clear example is ecore_con usage of connect() and getaddrinfo() in
threads. If the connect timeout expires, the thread will be cancelled,
but it was blocked on syscalls and they will hang around for long
time. If the application exits, ecore will print an error saying it
can SEGV.
Then enable access to pthread_setcancelstate(PTHREAD_CANCEL_ENABLE)
via eina_thread_cancellable_set(EINA_TRUE), to pthread_cancel() via
eina_thread_cancel(), to pthread_cleanup_push()/pthread_cleanup_pop()
via EINA_THREAD_CLEANUP_PUSH()/EINA_THREAD_CLEANUP_POP() and so on.
Ecore threads will enforce non-cancellable threads on its own code,
but the user may decide to enable that and allow cancellation, that's
not an issue since ecore_thread now plays well and use cleanup
functions.
Ecore con connect/resolve make use of that and enable cancellable
state, efl_net_dialer_tcp benefits a lot from that.
A good comparison of the benefit is to run:
./src/examples/ecore/efl_io_copier_example tcp://google.com:1234 :stdout:
before and after. It will timeout after 30s and with this patch the
thread is gone, no ecore error is printed about possible SEGV.
2016-09-13 21:38:58 -07:00
|
|
|
/* allows ecore_thread_cancel() to cancel at some points, see
|
|
|
|
* man:pthreads(7).
|
|
|
|
*
|
|
|
|
* no need to set cleanup functions since the main thread will
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
* handle that with _efl_net_connect_async_cancel().
|
eina/ecore: allow threads to be canceled, use in ecore_con.
As discussed in the mailing list, many people will use worker threads
to execute blocking syscalls and mandating ecore_thread_check() for
voluntary preemption reduces the ecore_thread usefulness a lot.
A clear example is ecore_con usage of connect() and getaddrinfo() in
threads. If the connect timeout expires, the thread will be cancelled,
but it was blocked on syscalls and they will hang around for long
time. If the application exits, ecore will print an error saying it
can SEGV.
Then enable access to pthread_setcancelstate(PTHREAD_CANCEL_ENABLE)
via eina_thread_cancellable_set(EINA_TRUE), to pthread_cancel() via
eina_thread_cancel(), to pthread_cleanup_push()/pthread_cleanup_pop()
via EINA_THREAD_CLEANUP_PUSH()/EINA_THREAD_CLEANUP_POP() and so on.
Ecore threads will enforce non-cancellable threads on its own code,
but the user may decide to enable that and allow cancellation, that's
not an issue since ecore_thread now plays well and use cleanup
functions.
Ecore con connect/resolve make use of that and enable cancellable
state, efl_net_dialer_tcp benefits a lot from that.
A good comparison of the benefit is to run:
./src/examples/ecore/efl_io_copier_example tcp://google.com:1234 :stdout:
before and after. It will timeout after 30s and with this patch the
thread is gone, no ecore error is printed about possible SEGV.
2016-09-13 21:38:58 -07:00
|
|
|
*/
|
|
|
|
eina_thread_cancellable_set(EINA_TRUE, NULL);
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d->error = 0;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
/* always close-on-exec since it's not a point to pass an
|
|
|
|
* under construction socket to a child process.
|
|
|
|
*/
|
|
|
|
d->sockfd = efl_net_socket4(d->addr->sa_family, d->type, d->protocol, EINA_TRUE);
|
|
|
|
if (d->sockfd < 0)
|
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
DBG("socket(%d, %d, %d) failed: %s", d->addr->sa_family, d->type, d->protocol, strerror(errno));
|
|
|
|
return;
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
efl_net_ip_port_fmt(buf, sizeof(buf), d->addr);
|
|
|
|
|
|
|
|
DBG("connecting fd=%d to %s", d->sockfd, buf);
|
|
|
|
|
|
|
|
r = connect(d->sockfd, d->addr, d->addrlen);
|
|
|
|
if (r < 0)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
int fd = d->sockfd;
|
|
|
|
d->error = errno;
|
|
|
|
d->sockfd = -1;
|
|
|
|
/* close() is a cancellation point, thus unset sockfd before
|
|
|
|
* closing, so the main thread _efl_net_connect_async_cancel()
|
|
|
|
* won't close it again.
|
|
|
|
*/
|
|
|
|
close(fd);
|
|
|
|
DBG("connect(%d, %s) failed: %s", fd, buf, strerror(errno));
|
|
|
|
return;
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
|
|
|
|
DBG("connected fd=%d to %s", d->sockfd, buf);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_connect_async_data_free(Efl_Net_Connect_Async_Data *d)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
|
|
|
free(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_connect_async_end(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Connect_Async_Data *d = data;
|
|
|
|
|
|
|
|
#ifdef FD_CLOEXEC
|
|
|
|
/* if it wasn't a close on exec, release the socket to be passed to child */
|
|
|
|
if ((!d->close_on_exec) && (d->sockfd >= 0))
|
|
|
|
{
|
|
|
|
int flags = fcntl(d->sockfd, F_GETFD);
|
|
|
|
if (flags < 0)
|
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
ERR("fcntl(%d, F_GETFD): %s", d->sockfd, strerror(errno));
|
|
|
|
close(d->sockfd);
|
|
|
|
d->sockfd = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags &= (~FD_CLOEXEC);
|
|
|
|
if (fcntl(d->sockfd, F_SETFD, flags) < 0)
|
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
ERR("fcntl(%d, F_SETFD, %#x): %s", d->sockfd, flags, strerror(errno));
|
|
|
|
close(d->sockfd);
|
|
|
|
d->sockfd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
d->cb((void *)d->data, d->addr, d->addrlen, d->sockfd, d->error);
|
|
|
|
_efl_net_connect_async_data_free(d);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_connect_async_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Connect_Async_Data *d = data;
|
|
|
|
if (d->sockfd >= 0) close(d->sockfd);
|
|
|
|
_efl_net_connect_async_data_free(d);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Ecore_Thread *
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
efl_net_connect_async_new(const struct sockaddr *addr, socklen_t addrlen, int type, int protocol, Eina_Bool close_on_exec, Efl_Net_Connect_Async_Cb cb, const void *data)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Connect_Async_Data *d;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(addr, NULL);
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(addrlen < 1, NULL);
|
2016-09-09 16:09:51 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d = malloc(sizeof(Efl_Net_Connect_Async_Data) + addrlen);
|
2016-09-09 16:09:51 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
|
|
|
|
|
|
|
|
d->cb = cb;
|
|
|
|
d->data = data;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d->addrlen = addrlen;
|
|
|
|
d->close_on_exec = close_on_exec;
|
|
|
|
d->type = type;
|
|
|
|
d->protocol = protocol;
|
|
|
|
memcpy(d->addr, addr, addrlen);
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d->sockfd = -1;
|
|
|
|
d->error = 0;
|
|
|
|
|
|
|
|
return ecore_thread_run(_efl_net_connect_async_run,
|
|
|
|
_efl_net_connect_async_end,
|
|
|
|
_efl_net_connect_async_cancel,
|
|
|
|
d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_efl_net_ip_no_proxy(const char *host, char * const *no_proxy_strv)
|
|
|
|
{
|
|
|
|
char * const *itr;
|
|
|
|
size_t host_len;
|
|
|
|
|
|
|
|
if (!no_proxy_strv)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
host_len = strlen(host);
|
|
|
|
for (itr = no_proxy_strv; *itr != NULL; itr++)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
const char *s = *itr;
|
|
|
|
size_t slen;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
/* '*' is not a glob/pattern, it matches all */
|
|
|
|
if (*s == '*') return EINA_TRUE;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
/* old timers use leading dot to avoid matching partial names
|
|
|
|
* due implementation bugs not required anymore
|
|
|
|
*/
|
|
|
|
if (*s == '.') s++;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
slen = strlen(s);
|
|
|
|
if (slen == 0) continue;
|
|
|
|
|
|
|
|
if (host_len < slen) continue;
|
|
|
|
if (memcmp(host + host_len - slen, s, slen) == 0)
|
|
|
|
{
|
|
|
|
if (slen == host_len)
|
|
|
|
return EINA_TRUE;
|
|
|
|
if (host[host_len - slen - 1] == '.')
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
typedef struct _Efl_Net_Ip_Connect_Async_Data
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
|
|
|
Efl_Net_Connect_Async_Cb cb;
|
|
|
|
const void *data;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
char *address;
|
|
|
|
char *proxy;
|
|
|
|
char *proxy_env;
|
|
|
|
char **no_proxy_strv;
|
2016-09-09 16:09:51 -07:00
|
|
|
socklen_t addrlen;
|
|
|
|
Eina_Bool close_on_exec;
|
|
|
|
int type;
|
|
|
|
int protocol;
|
|
|
|
int sockfd;
|
|
|
|
Eina_Error error;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
union {
|
|
|
|
struct sockaddr_in addr4;
|
|
|
|
struct sockaddr_in6 addr6;
|
|
|
|
struct sockaddr addr;
|
|
|
|
};
|
|
|
|
} Efl_Net_Ip_Connect_Async_Data;
|
|
|
|
|
|
|
|
static Eina_Error
|
|
|
|
_efl_net_ip_connect(const struct addrinfo *addr, int *sockfd)
|
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
Eina_Error ret = 0;
|
|
|
|
|
|
|
|
/* always close-on-exec since it's not a point to pass an
|
|
|
|
* under construction socket to a child process.
|
|
|
|
*/
|
|
|
|
fd = efl_net_socket4(addr->ai_family, addr->ai_socktype, addr->ai_protocol, EINA_TRUE);
|
|
|
|
if (fd < 0) ret = errno;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")] = "";
|
|
|
|
int r;
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
|
|
|
if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))
|
|
|
|
{
|
|
|
|
if (efl_net_ip_port_fmt(buf, sizeof(buf), addr->ai_addr))
|
|
|
|
DBG("connect fd=%d to %s", fd, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = connect(fd, addr->ai_addr, addr->ai_addrlen);
|
|
|
|
if (r == 0)
|
|
|
|
{
|
|
|
|
DBG("connected fd=%d to %s", fd, buf);
|
|
|
|
*sockfd = fd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = errno;
|
|
|
|
DBG("couldn't connect fd=%d to %s: %s", fd, buf, strerror(errno));
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_FALSE); /* we need sockfd on success */
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Error
|
|
|
|
_efl_net_ip_resolve_and_connect(const char *host, const char *port, int type, int protocol, int *sockfd, struct sockaddr *addr, socklen_t *p_addrlen)
|
|
|
|
{
|
|
|
|
struct addrinfo *results = NULL;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = type,
|
|
|
|
.ai_protocol = protocol,
|
|
|
|
.ai_family = AF_UNSPEC,
|
|
|
|
};
|
|
|
|
Eina_Error ret = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (strchr(host, ':')) hints.ai_family = AF_INET6;
|
|
|
|
|
|
|
|
do
|
|
|
|
r = getaddrinfo(host, port, &hints, &results);
|
|
|
|
while ((r == EAI_AGAIN) || ((r == EAI_SYSTEM) && (errno == EINTR)));
|
|
|
|
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
DBG("couldn't resolve host='%s', port='%s': %s",
|
|
|
|
host, port, gai_strerror(r));
|
|
|
|
ret = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
|
|
|
|
*sockfd = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct addrinfo *addrinfo;
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)freeaddrinfo, results);
|
|
|
|
for (addrinfo = results; addrinfo != NULL; addrinfo = addrinfo->ai_next)
|
|
|
|
{
|
|
|
|
if (addrinfo->ai_socktype != type) continue;
|
|
|
|
if (addrinfo->ai_protocol != protocol) continue;
|
|
|
|
ret = _efl_net_ip_connect(addrinfo, sockfd);
|
|
|
|
if (ret == 0)
|
|
|
|
{
|
|
|
|
memcpy(addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
|
|
|
*p_addrlen = addrinfo->ai_addrlen;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ret != 0)
|
|
|
|
ret = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_ip_connect_async_run_direct(Efl_Net_Ip_Connect_Async_Data *d, const char *host, const char *port)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
DBG("direct connection to %s:%s", host, port);
|
|
|
|
d->error = _efl_net_ip_resolve_and_connect(host, port, d->type, d->protocol, &d->sockfd, &d->addr, &d->addrlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_efl_net_ip_port_user_pass_split(char *buf, const char **p_host, const char **p_port, const char **p_user, const char **p_pass)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
p = strchr(buf, '@');
|
|
|
|
if (!p)
|
|
|
|
{
|
|
|
|
p = buf;
|
|
|
|
*p_user = NULL;
|
|
|
|
*p_pass = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
*p_user = buf;
|
|
|
|
*p = '\0';
|
|
|
|
p++;
|
|
|
|
|
|
|
|
s = strchr(*p_user, ':');
|
|
|
|
if (!s)
|
|
|
|
*p_pass = NULL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*s = '\0';
|
|
|
|
s++;
|
|
|
|
*p_pass = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return efl_net_ip_port_split(p, p_host, p_port);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks4_Request_Command {
|
|
|
|
EFL_NET_SOCKS4_REQUEST_COMMAND_CONNECT = 0x01,
|
|
|
|
EFL_NET_SOCKS4_REQUEST_COMMAND_BIND = 0x02
|
|
|
|
} Efl_Net_Socks4_Request_Command;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks4_Request {
|
|
|
|
uint8_t version; /* = 0x4 */
|
|
|
|
uint8_t command; /* Efl_Net_Socks4_Request_Command */
|
|
|
|
uint16_t port;
|
|
|
|
uint8_t ipv4[4];
|
|
|
|
char indent[];
|
|
|
|
} Efl_Net_Socks4_Request;
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks4_Reply_Status {
|
|
|
|
EFL_NET_SOCKS4_REPLY_STATUS_GRANTED = 0x5a,
|
|
|
|
EFL_NET_SOCKS4_REPLY_STATUS_REJECTED = 0x5b,
|
|
|
|
EFL_NET_SOCKS4_REPLY_STATUS_FAILED_INDENT = 0x5c,
|
|
|
|
EFL_NET_SOCKS4_REPLY_STATUS_FAILED_USER = 0x5d
|
|
|
|
} Efl_Net_Socks4_Reply_Status;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks4_Reply {
|
|
|
|
uint8_t null;
|
|
|
|
uint8_t status;
|
|
|
|
uint16_t port;
|
|
|
|
uint8_t ipv4[4];
|
|
|
|
} Efl_Net_Socks4_Reply;
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_efl_net_ip_connect_async_run_socks4_try(Efl_Net_Ip_Connect_Async_Data *d, const char *proxy_host, const char *proxy_port, const struct addrinfo *addrinfo, Efl_Net_Socks4_Request *request, size_t request_len)
|
|
|
|
{
|
|
|
|
char buf[INET_ADDRSTRLEN + sizeof(":65536")];
|
|
|
|
struct sockaddr_in *a = (struct sockaddr_in *)addrinfo->ai_addr;
|
|
|
|
struct sockaddr_storage proxy_addr;
|
|
|
|
socklen_t proxy_addrlen;
|
|
|
|
int fd;
|
|
|
|
Eina_Error err;
|
|
|
|
Eina_Bool ret = EINA_FALSE;
|
|
|
|
ssize_t s;
|
|
|
|
|
|
|
|
err = _efl_net_ip_resolve_and_connect(proxy_host, proxy_port, SOCK_STREAM, IPPROTO_TCP, &fd, (struct sockaddr *)&proxy_addr, &proxy_addrlen);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
DBG("couldn't connect to socks4://%s:%s: %s", proxy_host, proxy_port, eina_error_msg_get(err));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
return EINA_TRUE; /* no point in continuing on this error */
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
|
|
|
if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))
|
|
|
|
{
|
|
|
|
if (efl_net_ip_port_fmt(buf, sizeof(buf), addrinfo->ai_addr))
|
|
|
|
DBG("resolved address='%s' to %s. Connect using fd=%d socks4://%s:%s", d->address, buf, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
|
|
|
|
request->port = a->sin_port;
|
|
|
|
memcpy(request->ipv4, &a->sin_addr, 4);
|
|
|
|
|
|
|
|
s = send(fd, request, request_len, MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)request_len)
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't request connection to host=%s fd=%d socks4://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", request_len, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks4_Reply reply;
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv reply of connection to host=%s fd=%d socks4://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply.status != EFL_NET_SOCKS4_REPLY_STATUS_GRANTED)
|
|
|
|
DBG("rejected connection to host=%s fd=%d socks4://%s:%s: reason=%#x", buf, fd, proxy_host, proxy_port, reply.status);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&d->addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
|
|
|
d->addrlen = addrinfo->ai_addrlen;
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
ret = EINA_TRUE;
|
|
|
|
DBG("connected to host=%s fd=%d socks4://%s:%s", buf, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(!ret); /* we need fd on success, on failure just close it */
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_efl_net_ip_connect_async_run_socks4(Efl_Net_Ip_Connect_Async_Data *d, const char *host, const char *port, const char *proxy)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
const char *proxy_user, *proxy_pass, *proxy_host, *proxy_port;
|
|
|
|
struct addrinfo *results = NULL;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = d->type,
|
|
|
|
.ai_protocol = d->protocol,
|
|
|
|
.ai_family = AF_INET,
|
|
|
|
};
|
2016-09-09 16:09:51 -07:00
|
|
|
int r;
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (strchr(host, ':'))
|
|
|
|
{
|
|
|
|
DBG("SOCKSv4 only handles IPv4. Wanted host=%s", host);
|
|
|
|
d->error = EAFNOSUPPORT;
|
|
|
|
return;
|
|
|
|
}
|
eina/ecore: allow threads to be canceled, use in ecore_con.
As discussed in the mailing list, many people will use worker threads
to execute blocking syscalls and mandating ecore_thread_check() for
voluntary preemption reduces the ecore_thread usefulness a lot.
A clear example is ecore_con usage of connect() and getaddrinfo() in
threads. If the connect timeout expires, the thread will be cancelled,
but it was blocked on syscalls and they will hang around for long
time. If the application exits, ecore will print an error saying it
can SEGV.
Then enable access to pthread_setcancelstate(PTHREAD_CANCEL_ENABLE)
via eina_thread_cancellable_set(EINA_TRUE), to pthread_cancel() via
eina_thread_cancel(), to pthread_cleanup_push()/pthread_cleanup_pop()
via EINA_THREAD_CLEANUP_PUSH()/EINA_THREAD_CLEANUP_POP() and so on.
Ecore threads will enforce non-cancellable threads on its own code,
but the user may decide to enable that and allow cancellation, that's
not an issue since ecore_thread now plays well and use cleanup
functions.
Ecore con connect/resolve make use of that and enable cancellable
state, efl_net_dialer_tcp benefits a lot from that.
A good comparison of the benefit is to run:
./src/examples/ecore/efl_io_copier_example tcp://google.com:1234 :stdout:
before and after. It will timeout after 30s and with this patch the
thread is gone, no ecore error is printed about possible SEGV.
2016-09-13 21:38:58 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if ((d->type != SOCK_STREAM) || (d->protocol != IPPROTO_TCP))
|
|
|
|
{
|
|
|
|
DBG("SOCKSv4 only accepts TCP requests. Wanted type=%#x, protocol=%#x", d->type, d->protocol);
|
|
|
|
d->error = EPROTONOSUPPORT;
|
|
|
|
return;
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
DBG("proxy connection to %s:%s using socks4://%s", host, port, proxy);
|
|
|
|
|
|
|
|
str = strdup(proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, str);
|
|
|
|
|
|
|
|
if (!_efl_net_ip_port_user_pass_split(str, &proxy_host, &proxy_port, &proxy_user, &proxy_pass))
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
ERR("Invalid proxy string: socks4://%s", proxy);
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!proxy_user) proxy_user = "";
|
|
|
|
if (!proxy_port) proxy_port = "1080";
|
|
|
|
|
|
|
|
do
|
|
|
|
r = getaddrinfo(host, port, &hints, &results);
|
|
|
|
while ((r == EAI_AGAIN) || ((r == EAI_SYSTEM) && (errno == EINTR)));
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
DBG("couldn't resolve host='%s', port='%s': %s",
|
|
|
|
host, port, gai_strerror(r));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct addrinfo *addrinfo;
|
|
|
|
Efl_Net_Socks4_Request *request;
|
|
|
|
size_t request_len;
|
|
|
|
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)freeaddrinfo, results);
|
|
|
|
|
|
|
|
request_len = sizeof(Efl_Net_Socks4_Request) + strlen(proxy_user) + 1;
|
|
|
|
request = malloc(request_len);
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
request->version = 0x04;
|
|
|
|
request->command = EFL_NET_SOCKS4_REQUEST_COMMAND_CONNECT;
|
|
|
|
memcpy(request->indent, proxy_user, strlen(proxy_user) + 1);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, request);
|
|
|
|
for (addrinfo = results; addrinfo != NULL; addrinfo = addrinfo->ai_next)
|
|
|
|
{
|
|
|
|
if (addrinfo->ai_socktype != d->type) continue;
|
|
|
|
if (addrinfo->ai_protocol != d->protocol) continue;
|
|
|
|
if (addrinfo->ai_family != AF_INET) continue;
|
|
|
|
if (_efl_net_ip_connect_async_run_socks4_try(d, proxy_host, proxy_port, addrinfo, request, request_len))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(request) */
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* freeaddrinfo(results) */
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_efl_net_ip_connect_async_run_socks4a(Efl_Net_Ip_Connect_Async_Data *d, const char *host, const char *port, const char *proxy)
|
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
char *str;
|
|
|
|
const char *proxy_user, *proxy_pass, *proxy_host, *proxy_port;
|
|
|
|
struct sockaddr_storage proxy_addr;
|
|
|
|
socklen_t proxy_addrlen;
|
|
|
|
Eina_Error err;
|
|
|
|
struct addrinfo *results = NULL;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = d->type,
|
|
|
|
.ai_protocol = d->protocol,
|
|
|
|
.ai_family = AF_INET,
|
|
|
|
};
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (strchr(host, ':'))
|
|
|
|
{
|
|
|
|
DBG("SOCKSv4 only handles IPv4. Wanted host=%s", host);
|
|
|
|
d->error = EAFNOSUPPORT;
|
2016-09-09 16:09:51 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if ((d->type != SOCK_STREAM) || (d->protocol != IPPROTO_TCP))
|
|
|
|
{
|
|
|
|
DBG("SOCKSv4 only accepts TCP requests. Wanted type=%#x, protocol=%#x", d->type, d->protocol);
|
|
|
|
d->error = EPROTONOSUPPORT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("proxy connection to %s:%s using socks4a://%s", host, port, proxy);
|
|
|
|
|
|
|
|
str = strdup(proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, str);
|
|
|
|
|
|
|
|
if (!_efl_net_ip_port_user_pass_split(str, &proxy_host, &proxy_port, &proxy_user, &proxy_pass))
|
|
|
|
{
|
|
|
|
ERR("Invalid proxy string: socks4a://%s", proxy);
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!proxy_user) proxy_user = "";
|
|
|
|
if (!proxy_port) proxy_port = "1080";
|
|
|
|
|
|
|
|
err = _efl_net_ip_resolve_and_connect(proxy_host, proxy_port, SOCK_STREAM, IPPROTO_TCP, &fd, (struct sockaddr *)&proxy_addr, &proxy_addrlen);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
DBG("couldn't connect to socks4a://%s: %s", proxy, eina_error_msg_get(err));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("connected fd=%d to socks4a://%s", fd, proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
|
|
|
|
|
|
|
/* we just resolve the port number here */
|
|
|
|
do
|
|
|
|
r = getaddrinfo(NULL, port, &hints, &results);
|
|
|
|
while ((r == EAI_AGAIN) || ((r == EAI_SYSTEM) && (errno == EINTR)));
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
DBG("couldn't resolve port='%s': %s", port, gai_strerror(r));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct addrinfo *addrinfo;
|
|
|
|
Efl_Net_Socks4_Request *request;
|
|
|
|
size_t request_len;
|
|
|
|
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)freeaddrinfo, results);
|
|
|
|
|
|
|
|
request_len = sizeof(Efl_Net_Socks4_Request) + strlen(proxy_user) + 1 + strlen(host) + 1;
|
|
|
|
request = malloc(request_len);
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
request->version = 0x04;
|
|
|
|
request->command = EFL_NET_SOCKS4_REQUEST_COMMAND_CONNECT;
|
|
|
|
memcpy(request->indent, proxy_user, strlen(proxy_user) + 1);
|
|
|
|
memcpy(request->indent + strlen(proxy_user) + 1, host, strlen(host) + 1);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, request);
|
|
|
|
for (addrinfo = results; addrinfo != NULL; addrinfo = addrinfo->ai_next)
|
|
|
|
{
|
|
|
|
struct sockaddr_in *a = (struct sockaddr_in *)addrinfo->ai_addr;
|
|
|
|
ssize_t s;
|
|
|
|
|
|
|
|
if (addrinfo->ai_socktype != d->type) continue;
|
|
|
|
if (addrinfo->ai_protocol != d->protocol) continue;
|
|
|
|
if (addrinfo->ai_family != AF_INET) continue;
|
|
|
|
|
|
|
|
request->port = a->sin_port;
|
|
|
|
request->ipv4[0] = 0;
|
|
|
|
request->ipv4[1] = 0;
|
|
|
|
request->ipv4[2] = 0;
|
|
|
|
request->ipv4[3] = 255;
|
|
|
|
|
|
|
|
s = send(fd, request, request_len, MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)request_len)
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't send proxy request: %s", strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", request_len, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks4_Reply reply;
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv proxy reply: %s", strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply.status != EFL_NET_SOCKS4_REPLY_STATUS_GRANTED)
|
|
|
|
DBG("proxy rejected request status=%#x", reply.status);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->addr4.sin_family = AF_INET;
|
|
|
|
d->addr4.sin_port = a->sin_port;
|
|
|
|
memcpy(&d->addr4.sin_addr, reply.ipv4, 4);
|
|
|
|
d->addrlen = sizeof(struct sockaddr_in);
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(request) */
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* freeaddrinfo(results) */
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(d->sockfd == -1); /* we need fd only on success */
|
|
|
|
end:
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks5_Auth {
|
|
|
|
EFL_NET_SOCKS5_AUTH_NONE = 0x00,
|
|
|
|
EFL_NET_SOCKS5_AUTH_GSSAPI = 0x01,
|
|
|
|
EFL_NET_SOCKS5_AUTH_USER_PASS = 0x02,
|
|
|
|
EFL_NET_SOCKS5_AUTH_FAILED = 0xff
|
|
|
|
} Efl_Net_Socks5_Auth;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Greeting {
|
|
|
|
uint8_t version; /* = 0x5 */
|
|
|
|
uint8_t auths_count;
|
|
|
|
uint8_t auths[1]; /* series of Efl_Net_Socks5_Auth */
|
|
|
|
} Efl_Net_Socks5_Greeting;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Greeting_Reply {
|
|
|
|
uint8_t version; /* = 0x5 */
|
|
|
|
uint8_t auth; /* Efl_Net_Socks5_Auth */
|
|
|
|
} Efl_Net_Socks5_Greeting_Reply;
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks5_Request_Command {
|
|
|
|
EFL_NET_SOCKS5_REQUEST_COMMAND_TCP_CONNECT = 0x01,
|
|
|
|
EFL_NET_SOCKS5_REQUEST_COMMAND_TCP_BIND = 0x02,
|
|
|
|
EFL_NET_SOCKS5_REQUEST_COMMAND_UDP_ASSOCIATE = 0x03
|
|
|
|
} Efl_Net_Socks5_Request_Command;
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks5_Address_Type {
|
|
|
|
EFL_NET_SOCKS5_ADDRESS_TYPE_IPV4 = 0x01,
|
|
|
|
EFL_NET_SOCKS5_ADDRESS_TYPE_NAME = 0x03,
|
|
|
|
EFL_NET_SOCKS5_ADDRESS_TYPE_IPV6 = 0x04
|
|
|
|
} Efl_Net_Socks5_Address_Type;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Request {
|
|
|
|
uint8_t version; /* = 0x5 */
|
|
|
|
uint8_t command; /* Efl_Net_Socks5_Command */
|
|
|
|
uint8_t reserved;
|
|
|
|
uint8_t address_type; /* Efl_Net_Socks5_Address_Type */
|
|
|
|
/* follows:
|
|
|
|
* - one of:
|
|
|
|
* - 4 bytes for IPv4
|
|
|
|
* - 16 bytes for IPv6
|
|
|
|
* - 1 byte (size) + N bytes of name
|
|
|
|
* - uint16_t port
|
|
|
|
*/
|
|
|
|
} Efl_Net_Socks5_Request;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Address_Ipv4 {
|
|
|
|
uint8_t address[4];
|
|
|
|
uint16_t port;
|
|
|
|
} Efl_Net_Socks5_Address_Ipv4;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Address_Ipv6 {
|
|
|
|
uint8_t address[16];
|
|
|
|
uint16_t port;
|
|
|
|
} Efl_Net_Socks5_Address_Ipv6;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Request_Ipv4 {
|
|
|
|
Efl_Net_Socks5_Request base;
|
|
|
|
Efl_Net_Socks5_Address_Ipv4 ipv4;
|
|
|
|
} Efl_Net_Socks5_Request_Ipv4;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Request_Ipv6 {
|
|
|
|
Efl_Net_Socks5_Request base;
|
|
|
|
Efl_Net_Socks5_Address_Ipv6 ipv6;
|
|
|
|
} Efl_Net_Socks5_Request_Ipv6;
|
|
|
|
|
|
|
|
static Efl_Net_Socks5_Request *
|
|
|
|
efl_net_socks5_request_addr_new(Efl_Net_Socks5_Request_Command command, const struct sockaddr *addr, size_t *p_request_len)
|
|
|
|
{
|
|
|
|
if (addr->sa_family == AF_INET)
|
|
|
|
{
|
|
|
|
const struct sockaddr_in *a = (const struct sockaddr_in *)addr;
|
|
|
|
Efl_Net_Socks5_Request_Ipv4 *request;
|
|
|
|
|
|
|
|
*p_request_len = sizeof(Efl_Net_Socks5_Request_Ipv4);
|
|
|
|
request = malloc(*p_request_len);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(request, NULL);
|
|
|
|
request->base.version = 0x05;
|
|
|
|
request->base.command = command;
|
|
|
|
request->base.reserved = 0;
|
|
|
|
request->base.address_type = EFL_NET_SOCKS5_ADDRESS_TYPE_IPV4;
|
|
|
|
memcpy(request->ipv4.address, &a->sin_addr, 4);
|
|
|
|
request->ipv4.port = a->sin_port;
|
|
|
|
return &request->base;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr;
|
|
|
|
Efl_Net_Socks5_Request_Ipv6 *request;
|
|
|
|
|
|
|
|
*p_request_len = sizeof(Efl_Net_Socks5_Request_Ipv6);
|
|
|
|
request = malloc(*p_request_len);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(request, NULL);
|
|
|
|
request->base.version = 0x05;
|
|
|
|
request->base.command = command;
|
|
|
|
request->base.reserved = 0;
|
|
|
|
request->base.address_type = EFL_NET_SOCKS5_ADDRESS_TYPE_IPV6;
|
|
|
|
memcpy(request->ipv6.address, &a->sin6_addr, 16);
|
|
|
|
request->ipv6.port = a->sin6_port;
|
|
|
|
return &request->base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* port must be network endianess */
|
|
|
|
static Efl_Net_Socks5_Request *
|
|
|
|
efl_net_socks5_request_name_new(Efl_Net_Socks5_Request_Command command, const char *name, uint16_t port, size_t *p_request_len)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Request *request;
|
|
|
|
uint8_t namelen = strlen(name);
|
|
|
|
uint8_t *p;
|
|
|
|
|
|
|
|
*p_request_len = sizeof(Efl_Net_Socks5_Request) + 1 + namelen + 2;
|
|
|
|
request = malloc(*p_request_len);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(request, NULL);
|
|
|
|
request->version = 0x05;
|
|
|
|
request->command = command;
|
|
|
|
request->reserved = 0;
|
|
|
|
request->address_type = EFL_NET_SOCKS5_ADDRESS_TYPE_NAME;
|
|
|
|
|
|
|
|
p = (uint8_t *)request + sizeof(Efl_Net_Socks5_Request);
|
|
|
|
*p = namelen;
|
|
|
|
p++;
|
|
|
|
memcpy(p, name, namelen);
|
|
|
|
p += namelen;
|
|
|
|
|
|
|
|
memcpy(p, &port, sizeof(port));
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum _Efl_Net_Socks5_Reply_Status {
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_GRANTED = 0x00,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_GENERAL_FAILURE = 0x01,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_REJECTED_BY_RULESET = 0x02,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_NETWORK_UNREACHABLE = 0x03,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_HOST_UNREACHABLE = 0x04,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_CONNECTION_REFUSED = 0x05,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_TTL_EXPIRED = 0x06,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_PROTOCOL_ERROR = 0x07,
|
|
|
|
EFL_NET_SOCKS5_REPLY_STATUS_ADDRESS_TYPE_UNSUPORTED = 0x08,
|
|
|
|
} Efl_Net_Socks5_Reply_Status;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Reply {
|
|
|
|
uint8_t version; /* = 0x5 */
|
|
|
|
uint8_t status;
|
|
|
|
uint8_t null; /* = 0 */
|
|
|
|
uint8_t address_type; /* Efl_Net_Socks5_Address_Type */
|
|
|
|
/* follows:
|
|
|
|
* - one of:
|
|
|
|
* - 4 bytes for IPv4
|
|
|
|
* - 16 bytes for IPv6
|
|
|
|
* - 1 byte (size) + N bytes name
|
|
|
|
* - uint16_t port
|
|
|
|
*/
|
|
|
|
} Efl_Net_Socks5_Reply;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Reply_Ipv4 {
|
|
|
|
Efl_Net_Socks5_Reply base;
|
|
|
|
Efl_Net_Socks5_Address_Ipv4 ipv4;
|
|
|
|
} Efl_Net_Socks5_Reply_Ipv4;
|
|
|
|
|
|
|
|
typedef struct _Efl_Net_Socks5_Reply_Ipv6 {
|
|
|
|
Efl_Net_Socks5_Reply base;
|
|
|
|
Efl_Net_Socks5_Address_Ipv6 ipv6;
|
|
|
|
} Efl_Net_Socks5_Reply_Ipv6;
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_efl_net_ip_connect_async_run_socks5_auth_user_pass(int fd, const char *user, const char *pass, const char *proxy_protocol, const char *proxy_host, const char *proxy_port)
|
|
|
|
{
|
|
|
|
uint8_t user_len = user ? strlen(user) : 0;
|
|
|
|
uint8_t pass_len = pass ? strlen(pass) : 0;
|
|
|
|
size_t len = 1 + 1 + user_len + 1 + pass_len;
|
|
|
|
char *msg;
|
|
|
|
Eina_Bool ret = EINA_FALSE;
|
|
|
|
ssize_t s;
|
|
|
|
|
|
|
|
msg = malloc(len);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, msg);
|
|
|
|
|
|
|
|
msg[0] = 0x01; /* version */
|
|
|
|
msg[1] = user_len;
|
|
|
|
if (user) memcpy(msg + 1 + 1, user, user_len);
|
|
|
|
msg[1 + 1 + user_len] = pass_len;
|
|
|
|
if (pass) memcpy(msg + 1 + 1 + user_len + 1, pass, pass_len);
|
|
|
|
|
|
|
|
DBG("authenticate user='%s' pass=%hhu (bytes) to proxy %s://%s:%s", user, pass_len, proxy_protocol, proxy_host, proxy_port);
|
|
|
|
|
|
|
|
s = send(fd, msg, len, MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)len)
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't send user-password authentication to fd=%d %s://%s:%s: %s", fd, proxy_protocol, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send user-password authentication: need %zu, did %zd", len, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint8_t reply[2];
|
|
|
|
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv user-password authentication reply from fd=%d %s://%s:%s: %s", fd, proxy_protocol, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv user-password authentication reply: need %zu, did %zd", len, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply[1] != 0)
|
|
|
|
DBG("proxy authentication failed user='%s' pass=%hhu (bytes) to proxy %s://%s:%s: reason=%#x", user, pass_len, proxy_protocol, proxy_host, proxy_port, reply[1]);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("successfully authenticated user=%s with proxy fd=%d %s://%s:%s", user, fd, proxy_protocol, proxy_host, proxy_port);
|
|
|
|
ret = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_efl_net_ip_connect_async_run_socks5_try(Efl_Net_Ip_Connect_Async_Data *d, const char *proxy_host, const char *proxy_port, const char *proxy_user, const char *proxy_pass, Efl_Net_Socks5_Request_Command cmd, const struct addrinfo *addrinfo)
|
|
|
|
{
|
|
|
|
char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")];
|
|
|
|
Efl_Net_Socks5_Greeting greeting = {
|
|
|
|
.version = 0x05,
|
|
|
|
.auths_count = 1,
|
|
|
|
.auths = { proxy_user ? EFL_NET_SOCKS5_AUTH_USER_PASS : EFL_NET_SOCKS5_AUTH_NONE },
|
|
|
|
};
|
|
|
|
struct sockaddr_storage proxy_addr;
|
|
|
|
socklen_t proxy_addrlen;
|
|
|
|
int fd;
|
|
|
|
Eina_Error err;
|
|
|
|
Eina_Bool ret = EINA_FALSE;
|
|
|
|
ssize_t s;
|
|
|
|
|
|
|
|
err = _efl_net_ip_resolve_and_connect(proxy_host, proxy_port, SOCK_STREAM, IPPROTO_TCP, &fd, (struct sockaddr *)&proxy_addr, &proxy_addrlen);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
DBG("couldn't connect to socks5://%s:%s: %s", proxy_host, proxy_port, eina_error_msg_get(err));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
return EINA_TRUE; /* no point in continuing on this error */
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
2016-09-09 16:09:51 -07:00
|
|
|
if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
{
|
|
|
|
if (efl_net_ip_port_fmt(buf, sizeof(buf), addrinfo->ai_addr))
|
|
|
|
DBG("resolved address='%s' to %s. Connect using fd=%d socks5://%s:%s", d->address, buf, fd, proxy_host, proxy_port);
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
s = send(fd, &greeting, sizeof(greeting), MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)sizeof(greeting))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't request connection to host=%s fd=%d socks5://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", sizeof(greeting), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Greeting_Reply greeting_reply;
|
|
|
|
s = recv(fd, &greeting_reply, sizeof(greeting_reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(greeting_reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv greeting reply of connection to host=%s fd=%d socks5://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(greeting_reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (greeting_reply.auth != greeting.auths[0])
|
|
|
|
DBG("proxy server rejected authentication %#x trying connection to host=%s fd=%d socks5://%s:%s", greeting.auths[0], buf, fd, proxy_host, proxy_port);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((greeting_reply.auth == EFL_NET_SOCKS5_AUTH_USER_PASS) &&
|
|
|
|
(!_efl_net_ip_connect_async_run_socks5_auth_user_pass(fd, proxy_user, proxy_pass, "socks5", proxy_host, proxy_port)))
|
|
|
|
{
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_PROXY_AUTHENTICATION_FAILED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Request *request;
|
|
|
|
size_t request_len;
|
|
|
|
|
|
|
|
request = efl_net_socks5_request_addr_new(cmd, addrinfo->ai_addr, &request_len);
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, request);
|
|
|
|
|
|
|
|
s = send(fd, request, request_len, MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)request_len)
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't request connection to host=%s fd=%d socks5://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", request_len, s);
|
|
|
|
}
|
|
|
|
else if (addrinfo->ai_family == AF_INET)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Reply_Ipv4 reply;
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv reply of connection to host=%s fd=%d socks5://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply.base.status != EFL_NET_SOCKS5_REPLY_STATUS_GRANTED)
|
|
|
|
DBG("rejected IPv4 connection to host=%s fd=%d socks5://%s:%s: reason=%#x", buf, fd, proxy_host, proxy_port, reply.base.status);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&d->addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
|
|
|
d->addrlen = addrinfo->ai_addrlen;
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
ret = EINA_TRUE;
|
|
|
|
DBG("connected IPv4 to host=%s fd=%d socks5://%s:%s", buf, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (addrinfo->ai_family == AF_INET6)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Reply_Ipv6 reply;
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv reply of connection to host=%s fd=%d socks5://%s:%s: %s", buf, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply.base.status != EFL_NET_SOCKS5_REPLY_STATUS_GRANTED)
|
|
|
|
DBG("rejected IPv6 connection to host=%s fd=%d socks5://%s:%s: reason=%#x", buf, fd, proxy_host, proxy_port, reply.base.status);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(&d->addr, addrinfo->ai_addr, addrinfo->ai_addrlen);
|
|
|
|
d->addrlen = addrinfo->ai_addrlen;
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
ret = EINA_TRUE;
|
|
|
|
DBG("connected IPv6 to host=%s fd=%d socks5://%s:%s", buf, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(!ret); /* we need fd on success, on failure just close it */
|
|
|
|
return ret;
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
static void
|
|
|
|
_efl_net_ip_connect_async_run_socks5(Efl_Net_Ip_Connect_Async_Data *d, const char *host, const char *port, const char *proxy)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
const char *proxy_user, *proxy_pass, *proxy_host, *proxy_port;
|
|
|
|
struct addrinfo *results = NULL;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = d->type,
|
|
|
|
.ai_protocol = d->protocol,
|
|
|
|
.ai_family = AF_UNSPEC,
|
|
|
|
};
|
|
|
|
Efl_Net_Socks5_Request_Command cmd;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((d->type == SOCK_STREAM) && (d->protocol == IPPROTO_TCP))
|
|
|
|
cmd = EFL_NET_SOCKS5_REQUEST_COMMAND_TCP_CONNECT;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("EFL SOCKSv5 only accepts TCP requests at this moment. Wanted type=%#x, protocol=%#x", d->type, d->protocol);
|
|
|
|
d->error = EPROTONOSUPPORT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(host, ':')) hints.ai_family = AF_INET6;
|
|
|
|
|
|
|
|
DBG("proxy connection to %s:%s using socks5://%s", host, port, proxy);
|
|
|
|
|
|
|
|
str = strdup(proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, str);
|
|
|
|
|
|
|
|
if (!_efl_net_ip_port_user_pass_split(str, &proxy_host, &proxy_port, &proxy_user, &proxy_pass))
|
|
|
|
{
|
|
|
|
ERR("Invalid proxy string: socks5://%s", proxy);
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!proxy_port) proxy_port = "1080";
|
|
|
|
|
|
|
|
do
|
|
|
|
r = getaddrinfo(host, port, &hints, &results);
|
|
|
|
while ((r == EAI_AGAIN) || ((r == EAI_SYSTEM) && (errno == EINTR)));
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
DBG("couldn't resolve host='%s', port='%s': %s",
|
|
|
|
host, port, gai_strerror(r));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct addrinfo *addrinfo;
|
|
|
|
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)freeaddrinfo, results);
|
|
|
|
for (addrinfo = results; addrinfo != NULL; addrinfo = addrinfo->ai_next)
|
|
|
|
{
|
|
|
|
if (addrinfo->ai_socktype != d->type) continue;
|
|
|
|
if (addrinfo->ai_protocol != d->protocol) continue;
|
|
|
|
if (_efl_net_ip_connect_async_run_socks5_try(d, proxy_host, proxy_port, proxy_user, proxy_pass, cmd, addrinfo))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* freeaddrinfo(results) */
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_efl_net_ip_connect_async_run_socks5h(Efl_Net_Ip_Connect_Async_Data *d, const char *host, const char *port, const char *proxy)
|
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
char *str;
|
|
|
|
const char *proxy_user, *proxy_pass, *proxy_host, *proxy_port;
|
|
|
|
struct sockaddr_storage proxy_addr;
|
|
|
|
socklen_t proxy_addrlen;
|
|
|
|
Eina_Error err;
|
|
|
|
Efl_Net_Socks5_Greeting greeting = {
|
|
|
|
.version = 0x05,
|
|
|
|
.auths_count = 1,
|
|
|
|
};
|
|
|
|
Efl_Net_Socks5_Request_Command cmd;
|
|
|
|
ssize_t s;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((d->type == SOCK_STREAM) && (d->protocol == IPPROTO_TCP))
|
|
|
|
cmd = EFL_NET_SOCKS5_REQUEST_COMMAND_TCP_CONNECT;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("EFL SOCKSv5 only accepts TCP requests at this moment. Wanted type=%#x, protocol=%#x", d->type, d->protocol);
|
|
|
|
d->error = EPROTONOSUPPORT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("proxy connection to %s:%s using socks5h://%s", host, port, proxy);
|
|
|
|
|
|
|
|
str = strdup(proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, str);
|
|
|
|
|
|
|
|
if (!_efl_net_ip_port_user_pass_split(str, &proxy_host, &proxy_port, &proxy_user, &proxy_pass))
|
|
|
|
{
|
|
|
|
ERR("Invalid proxy string: socks5h://%s", proxy);
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!proxy_port) proxy_port = "1080";
|
|
|
|
|
|
|
|
greeting.auths[0] = proxy_user ? EFL_NET_SOCKS5_AUTH_USER_PASS : EFL_NET_SOCKS5_AUTH_NONE;
|
|
|
|
|
|
|
|
err = _efl_net_ip_resolve_and_connect(proxy_host, proxy_port, SOCK_STREAM, IPPROTO_TCP, &fd, (struct sockaddr *)&proxy_addr, &proxy_addrlen);
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
DBG("couldn't connect to socks5h://%s: %s", proxy, eina_error_msg_get(err));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("connected fd=%d to socks5h://%s", fd, proxy);
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(_cleanup_close, &fd);
|
|
|
|
|
|
|
|
s = send(fd, &greeting, sizeof(greeting), MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)sizeof(greeting))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't request connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", sizeof(greeting), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Greeting_Reply greeting_reply;
|
|
|
|
s = recv(fd, &greeting_reply, sizeof(greeting_reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(greeting_reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv greeting reply of connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(greeting_reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (greeting_reply.auth != greeting.auths[0])
|
|
|
|
DBG("proxy server rejected authentication %#x trying connection to host=%s:%s fd=%d socks5h://%s:%s", greeting.auths[0], host, port, fd, proxy_host, proxy_port);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((greeting_reply.auth == EFL_NET_SOCKS5_AUTH_USER_PASS) &&
|
|
|
|
(!_efl_net_ip_connect_async_run_socks5_auth_user_pass(fd, proxy_user, proxy_pass, "socks5h", proxy_host, proxy_port)))
|
|
|
|
{
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_PROXY_AUTHENTICATION_FAILED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct addrinfo *results = NULL;
|
|
|
|
struct addrinfo hints = {
|
|
|
|
.ai_socktype = d->type,
|
|
|
|
.ai_protocol = d->protocol,
|
|
|
|
.ai_family = AF_UNSPEC,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (strchr(host, ':')) hints.ai_family = AF_INET6;
|
|
|
|
|
|
|
|
/* we just resolve the port number here */
|
|
|
|
do
|
|
|
|
r = getaddrinfo(NULL, port, &hints, &results);
|
|
|
|
while ((r == EAI_AGAIN) || ((r == EAI_SYSTEM) && (errno == EINTR)));
|
|
|
|
if (r != 0)
|
|
|
|
{
|
|
|
|
DBG("couldn't resolve port='%s': %s", port, gai_strerror(r));
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const struct addrinfo *addrinfo;
|
|
|
|
|
|
|
|
d->error = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
|
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)freeaddrinfo, results);
|
|
|
|
for (addrinfo = results; addrinfo != NULL; addrinfo = addrinfo->ai_next)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Request *request;
|
|
|
|
size_t request_len;
|
|
|
|
uint16_t port_num;
|
|
|
|
|
|
|
|
if (addrinfo->ai_socktype != d->type) continue;
|
|
|
|
if (addrinfo->ai_protocol != d->protocol) continue;
|
|
|
|
|
|
|
|
if (addrinfo->ai_family == AF_INET)
|
|
|
|
port_num = ((const struct sockaddr_in *)addrinfo->ai_addr)->sin_port;
|
|
|
|
else
|
|
|
|
port_num = ((const struct sockaddr_in6 *)addrinfo->ai_addr)->sin6_port;
|
|
|
|
|
|
|
|
request = efl_net_socks5_request_name_new(cmd, host, port_num, &request_len);
|
|
|
|
if (request)
|
|
|
|
{
|
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, request);
|
|
|
|
|
|
|
|
s = send(fd, request, request_len, MSG_NOSIGNAL);
|
|
|
|
if (s != (ssize_t)request_len)
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't request connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't send proxy request: need %zu, did %zd", request_len, s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Reply reply;
|
|
|
|
|
|
|
|
s = recv(fd, &reply, sizeof(reply), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(reply))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv reply of connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy reply: need %zu, did %zd", sizeof(reply), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (reply.status != EFL_NET_SOCKS5_REPLY_STATUS_GRANTED)
|
|
|
|
DBG("rejected connection to host=%s:%s fd=%d socks5h://%s:%s: reason=%#x", host, port, fd, proxy_host, proxy_port, reply.status);
|
|
|
|
else if (reply.address_type == EFL_NET_SOCKS5_ADDRESS_TYPE_IPV4)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Address_Ipv4 ipv4;
|
|
|
|
|
|
|
|
s = recv(fd, &ipv4, sizeof(ipv4), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(ipv4))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv ipv4 of connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy ipv4: need %zu, did %zd", sizeof(ipv4), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->addr4.sin_family = AF_INET;
|
|
|
|
d->addr4.sin_port = ipv4.port;
|
|
|
|
memcpy(&d->addr4.sin_addr, ipv4.address, 4);
|
|
|
|
d->addrlen = sizeof(struct sockaddr_in);
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
DBG("connected IPv4 to host=%s:%s fd=%d socks5h://%s:%s", host, port, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (reply.address_type == EFL_NET_SOCKS5_ADDRESS_TYPE_IPV6)
|
|
|
|
{
|
|
|
|
Efl_Net_Socks5_Address_Ipv6 ipv6;
|
|
|
|
|
|
|
|
s = recv(fd, &ipv6, sizeof(ipv6), MSG_NOSIGNAL);
|
|
|
|
if (s != sizeof(ipv6))
|
|
|
|
{
|
|
|
|
if (s < 0)
|
|
|
|
DBG("couldn't recv ipv6 of connection to host=%s:%s fd=%d socks5h://%s:%s: %s", host, port, fd, proxy_host, proxy_port, strerror(errno));
|
|
|
|
else
|
|
|
|
DBG("couldn't recv proxy ipv6: need %zu, did %zd", sizeof(ipv6), s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->addr6.sin6_family = AF_INET;
|
|
|
|
d->addr6.sin6_port = ipv6.port;
|
|
|
|
memcpy(&d->addr6.sin6_addr, ipv6.address, 16);
|
|
|
|
d->addrlen = sizeof(struct sockaddr_in);
|
|
|
|
d->sockfd = fd;
|
|
|
|
d->error = 0;
|
|
|
|
DBG("connected IPv6 to host=%s:%s fd=%d socks5h://%s:%s", host, port, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* most proxy servers will return a failure instead of this, but let's guard and log */
|
|
|
|
DBG("couldn't resolve host %s:%s fd=%d socks5h://%s:%s", host, port, fd, proxy_host, proxy_port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(request) */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* freeaddrinfo(results) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EINA_THREAD_CLEANUP_POP(d->sockfd == -1); /* we need fd only on success */
|
|
|
|
end:
|
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE); /* free(str) */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_efl_net_ip_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Net_Ip_Connect_Async_Data *d = data;
|
|
|
|
const char *host, *port, *proxy;
|
|
|
|
char *addrcopy;
|
2016-09-18 23:19:16 -07:00
|
|
|
char **proxies = NULL;
|
|
|
|
int proxies_idx = 0;
|
|
|
|
Eina_Bool is_libproxy = EINA_FALSE;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
|
|
|
|
addrcopy = strdup(d->address);
|
|
|
|
if (!addrcopy)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (!efl_net_ip_port_split(addrcopy, &host, &port))
|
|
|
|
{
|
|
|
|
d->error = EINVAL;
|
|
|
|
free(addrcopy);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!port) port = "0";
|
2016-09-18 23:19:16 -07:00
|
|
|
EINA_THREAD_CLEANUP_PUSH(free, addrcopy);
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
|
|
|
|
proxy = d->proxy;
|
2016-09-18 23:19:16 -07:00
|
|
|
|
2016-09-20 11:00:17 -07:00
|
|
|
if ((!proxy) && (_ecore_con_libproxy.factory))
|
2016-09-18 23:19:16 -07:00
|
|
|
{
|
|
|
|
/* libproxy is thread-safe but not cancellable. the provided
|
|
|
|
* parameter must be a URL with schema, otherwise it won't
|
|
|
|
* return anything.
|
|
|
|
*/
|
|
|
|
char *url;
|
|
|
|
|
|
|
|
asprintf(&url, "%s://%s:%s", d->protocol == IPPROTO_UDP ? "udp" : "tcp", host, port);
|
2016-09-20 11:00:17 -07:00
|
|
|
proxies = ecore_con_libproxy_proxies_get(url);
|
2016-09-18 23:19:16 -07:00
|
|
|
free(url);
|
|
|
|
}
|
|
|
|
|
2016-09-20 11:00:17 -07:00
|
|
|
EINA_THREAD_CLEANUP_PUSH((Eina_Free_Cb)ecore_con_libproxy_proxies_free, proxies);
|
2016-09-18 23:19:16 -07:00
|
|
|
next_proxy:
|
|
|
|
if ((!proxy) && (proxies) && (proxies_idx >= 0))
|
|
|
|
{
|
|
|
|
proxy = proxies[proxies_idx];
|
|
|
|
if (!proxy)
|
|
|
|
{
|
|
|
|
is_libproxy = EINA_FALSE;
|
|
|
|
proxies_idx = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (strcmp(proxy, "direct://") == 0)
|
|
|
|
{
|
|
|
|
/* give a chance to try envvars */
|
|
|
|
proxy = NULL;
|
|
|
|
is_libproxy = EINA_FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("libproxy said %s for host='%s' port='%s'", proxy, host, port);
|
|
|
|
is_libproxy = EINA_TRUE;
|
|
|
|
}
|
|
|
|
proxies_idx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
if (!proxy)
|
|
|
|
{
|
|
|
|
proxy = d->proxy_env;
|
|
|
|
if (!proxy)
|
|
|
|
proxy = "";
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (_efl_net_ip_no_proxy(host, d->no_proxy_strv))
|
|
|
|
proxy = "";
|
2016-09-18 23:19:16 -07:00
|
|
|
else
|
|
|
|
DBG("using proxy %s from envvar", proxy);
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allows ecore_thread_cancel() to cancel at some points, see
|
|
|
|
* man:pthreads(7).
|
|
|
|
*/
|
|
|
|
eina_thread_cancellable_set(EINA_TRUE, NULL);
|
|
|
|
|
|
|
|
if (!proxy[0])
|
|
|
|
_efl_net_ip_connect_async_run_direct(d, host, port);
|
|
|
|
else if (eina_str_has_prefix(proxy, "socks4://"))
|
|
|
|
_efl_net_ip_connect_async_run_socks4(d, host, port, proxy + strlen("socks4://"));
|
|
|
|
else if (eina_str_has_prefix(proxy, "socks5://"))
|
|
|
|
_efl_net_ip_connect_async_run_socks5(d, host, port, proxy + strlen("socks5://"));
|
|
|
|
else if (eina_str_has_prefix(proxy, "socks4a://"))
|
|
|
|
_efl_net_ip_connect_async_run_socks4a(d, host, port, proxy + strlen("socks4a://"));
|
|
|
|
else if (eina_str_has_prefix(proxy, "socks5h://"))
|
|
|
|
_efl_net_ip_connect_async_run_socks5h(d, host, port, proxy + strlen("socks5h://"));
|
2016-09-18 23:19:16 -07:00
|
|
|
else if (eina_str_has_prefix(proxy, "socks://"))
|
|
|
|
{
|
|
|
|
_efl_net_ip_connect_async_run_socks5(d, host, port, proxy + strlen("socks://"));
|
|
|
|
if (d->error)
|
|
|
|
_efl_net_ip_connect_async_run_socks4(d, host, port, proxy + strlen("socks://"));
|
|
|
|
}
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
else if (!strstr(proxy, "://"))
|
|
|
|
{
|
|
|
|
_efl_net_ip_connect_async_run_socks5(d, host, port, proxy);
|
|
|
|
if (d->error)
|
|
|
|
_efl_net_ip_connect_async_run_socks4(d, host, port, proxy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (d->proxy)
|
|
|
|
{
|
|
|
|
d->error = ENOTSUP;
|
|
|
|
ERR("proxy protocol not supported '%s'", proxy);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-09-18 23:19:16 -07:00
|
|
|
if (is_libproxy)
|
|
|
|
{
|
|
|
|
DBG("libproxy said %s but it's not supported, try next proxy", proxy);
|
|
|
|
proxy = NULL;
|
|
|
|
goto next_proxy;
|
|
|
|
}
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
/* maybe bogus envvar, ignore it */
|
|
|
|
WRN("proxy protocol not supported '%s', connect directly", proxy);
|
|
|
|
_efl_net_ip_connect_async_run_direct(d, host, port);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((d->error) && (!d->proxy) && (proxy[0] != '\0'))
|
|
|
|
{
|
2016-09-18 23:19:16 -07:00
|
|
|
if (is_libproxy)
|
|
|
|
{
|
|
|
|
DBG("libproxy said %s but it failed, try next proxy", proxy);
|
|
|
|
proxy = NULL;
|
|
|
|
goto next_proxy;
|
|
|
|
}
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
WRN("error using proxy '%s' from environment, try direct connect", proxy);
|
|
|
|
_efl_net_ip_connect_async_run_direct(d, host, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_thread_cancellable_set(EINA_FALSE, NULL);
|
2016-09-18 23:19:16 -07:00
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE);
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EINA_THREAD_CLEANUP_POP(EINA_TRUE);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_ip_connect_async_data_free(Efl_Net_Ip_Connect_Async_Data *d)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
free(d->address);
|
|
|
|
free(d->proxy);
|
|
|
|
free(d->proxy_env);
|
|
|
|
if (d->no_proxy_strv)
|
|
|
|
{
|
|
|
|
free(d->no_proxy_strv[0]);
|
|
|
|
free(d->no_proxy_strv);
|
|
|
|
}
|
2016-09-09 16:09:51 -07:00
|
|
|
free(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_ip_connect_async_end(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Ip_Connect_Async_Data *d = data;
|
|
|
|
|
|
|
|
#ifdef FD_CLOEXEC
|
|
|
|
/* if it wasn't a close on exec, release the socket to be passed to child */
|
|
|
|
if ((!d->close_on_exec) && (d->sockfd >= 0))
|
|
|
|
{
|
|
|
|
int flags = fcntl(d->sockfd, F_GETFD);
|
|
|
|
if (flags < 0)
|
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
ERR("fcntl(%d, F_GETFD): %s", d->sockfd, strerror(errno));
|
|
|
|
close(d->sockfd);
|
|
|
|
d->sockfd = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags &= (~FD_CLOEXEC);
|
|
|
|
if (fcntl(d->sockfd, F_SETFD, flags) < 0)
|
|
|
|
{
|
|
|
|
d->error = errno;
|
|
|
|
ERR("fcntl(%d, F_SETFD, %#x): %s", d->sockfd, flags, strerror(errno));
|
|
|
|
close(d->sockfd);
|
|
|
|
d->sockfd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
d->cb((void *)d->data, &d->addr, d->addrlen, d->sockfd, d->error);
|
|
|
|
_efl_net_ip_connect_async_data_free(d);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_ip_connect_async_cancel(void *data, Ecore_Thread *thread EINA_UNUSED)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Ip_Connect_Async_Data *d = data;
|
2016-09-09 16:09:51 -07:00
|
|
|
if (d->sockfd >= 0) close(d->sockfd);
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
_efl_net_ip_connect_async_data_free(d);
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Ecore_Thread *
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
efl_net_ip_connect_async_new(const char *address, const char *proxy, const char *proxy_env, const char *no_proxy_env, int type, int protocol, Eina_Bool close_on_exec, Efl_Net_Connect_Async_Cb cb, const void *data)
|
2016-09-09 16:09:51 -07:00
|
|
|
{
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
Efl_Net_Ip_Connect_Async_Data *d;
|
2016-09-09 16:09:51 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(address, NULL);
|
2016-09-09 16:09:51 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d = calloc(1, sizeof(Efl_Net_Ip_Connect_Async_Data));
|
2016-09-09 16:09:51 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
|
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d->address = strdup(address);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(d->address, error_address);
|
|
|
|
|
|
|
|
if (proxy)
|
|
|
|
{
|
|
|
|
d->proxy = strdup(proxy);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(d->proxy, error_proxy);
|
|
|
|
}
|
|
|
|
if (proxy_env)
|
|
|
|
{
|
|
|
|
d->proxy_env = strdup(proxy_env);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(d->proxy_env, error_proxy_env);
|
|
|
|
}
|
|
|
|
if (no_proxy_env)
|
|
|
|
{
|
|
|
|
d->no_proxy_strv = eina_str_split(no_proxy_env, ",", 0);
|
|
|
|
EINA_SAFETY_ON_NULL_GOTO(d->no_proxy_strv, error_no_proxy_strv);
|
|
|
|
}
|
|
|
|
|
2016-09-09 16:09:51 -07:00
|
|
|
d->cb = cb;
|
|
|
|
d->data = data;
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
d->addrlen = 0;
|
2016-09-09 16:09:51 -07:00
|
|
|
d->close_on_exec = close_on_exec;
|
|
|
|
d->type = type;
|
|
|
|
d->protocol = protocol;
|
|
|
|
|
|
|
|
d->sockfd = -1;
|
|
|
|
d->error = 0;
|
|
|
|
|
2016-09-18 23:19:16 -07:00
|
|
|
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
return ecore_thread_run(_efl_net_ip_connect_async_run,
|
|
|
|
_efl_net_ip_connect_async_end,
|
|
|
|
_efl_net_ip_connect_async_cancel,
|
2016-09-09 16:09:51 -07:00
|
|
|
d);
|
efl_net_dialer_tcp: add SOCKS proxy support.
SOCKS is implemented in its own thread using synchronous/blocking
primitives, which simplifies the code a lot -- as well as simulate the
usage of Ecore_Thread as our users will likely do.
Since SOCKSv4a and SOCKSv5 allow name resolution, the whole
getaddrinfo() is done in the same thread, when needed, instead of a
separate thread to do that, which should also save some resources.
Instead of the legacy ECORE_CON_SOCKS_V4 and ECORE_CON_SOCKS_V5, now
we use socks_proxy, all_proxy and no_proxy. This matches our other
dialers http/websocket (which will use http_proxy, all_proxy and
no_proxy). If desired it's easy to add back support for those
variables, but I think we should just deprecate them. (The legacy code
will keep unchanged, thus direct users of ecore_con_server will still
use those -- just the previous users of ecore_con_server will be
converted to use the new API).
2016-09-18 20:56:18 -07:00
|
|
|
|
|
|
|
error_no_proxy_strv:
|
|
|
|
free(d->proxy_env);
|
|
|
|
error_proxy_env:
|
|
|
|
free(d->proxy);
|
|
|
|
error_proxy:
|
|
|
|
free(d->address);
|
|
|
|
error_address:
|
|
|
|
free(d);
|
|
|
|
return NULL;
|
2016-09-09 16:09:51 -07:00
|
|
|
}
|
2016-09-20 11:00:17 -07:00
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
ecore_con_libproxy_init(void)
|
|
|
|
{
|
|
|
|
if (!_ecore_con_libproxy.mod)
|
|
|
|
{
|
|
|
|
#define LOAD(x) \
|
|
|
|
if (!_ecore_con_libproxy.mod) { \
|
|
|
|
_ecore_con_libproxy.mod = eina_module_new(x); \
|
|
|
|
if (_ecore_con_libproxy.mod) { \
|
|
|
|
if (!eina_module_load(_ecore_con_libproxy.mod)) { \
|
|
|
|
eina_module_free(_ecore_con_libproxy.mod); \
|
|
|
|
_ecore_con_libproxy.mod = NULL; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
|
|
LOAD("libproxy-1.dll");
|
|
|
|
LOAD("libproxy.dll");
|
|
|
|
#elif defined(__APPLE__) && defined(__MACH__)
|
|
|
|
LOAD("libproxy.1.dylib");
|
|
|
|
LOAD("libproxy.dylib");
|
|
|
|
#else
|
|
|
|
LOAD("libproxy.so.1");
|
|
|
|
LOAD("libproxy.so");
|
|
|
|
#endif
|
|
|
|
#undef LOAD
|
|
|
|
if (!_ecore_con_libproxy.mod)
|
|
|
|
{
|
|
|
|
DBG("Couldn't find libproxy in your system. Continue without it");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SYM(x) \
|
|
|
|
if ((_ecore_con_libproxy.x = eina_module_symbol_get(_ecore_con_libproxy.mod, #x)) == NULL) { \
|
|
|
|
ERR("libproxy (%s) missing symbol %s", eina_module_file_get(_ecore_con_libproxy.mod), #x); \
|
|
|
|
eina_module_free(_ecore_con_libproxy.mod); \
|
|
|
|
_ecore_con_libproxy.mod = NULL; \
|
|
|
|
return EINA_FALSE; \
|
|
|
|
}
|
|
|
|
|
|
|
|
SYM(px_proxy_factory_new);
|
|
|
|
SYM(px_proxy_factory_free);
|
|
|
|
SYM(px_proxy_factory_get_proxies);
|
|
|
|
#undef SYM
|
|
|
|
DBG("using libproxy=%s", eina_module_file_get(_ecore_con_libproxy.mod));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_ecore_con_libproxy.factory)
|
|
|
|
_ecore_con_libproxy.factory = _ecore_con_libproxy.px_proxy_factory_new();
|
|
|
|
|
|
|
|
return !!_ecore_con_libproxy.factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
char **
|
|
|
|
ecore_con_libproxy_proxies_get(const char *url)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_con_libproxy.px_proxy_factory_get_proxies, NULL);
|
|
|
|
return _ecore_con_libproxy.px_proxy_factory_get_proxies(_ecore_con_libproxy.factory, url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ecore_con_libproxy_proxies_free(char **proxies)
|
|
|
|
{
|
|
|
|
char **itr;
|
|
|
|
|
|
|
|
if (!proxies) return;
|
|
|
|
|
|
|
|
for (itr = proxies; *itr != NULL; itr++)
|
|
|
|
free(*itr);
|
|
|
|
free(proxies);
|
|
|
|
}
|