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
2016-11-16 01:26:56 -08:00
# ifdef HAVE_SYS_IOCTL_H
# include <sys / ioctl.h>
# endif
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-10-20 07:44:20 -07:00
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_CONNECT = 0 ;
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_PROXY = 0 ;
EWAPI Eina_Error EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST = 0 ;
EWAPI Eina_Error EFL_NET_DIALER_ERROR_PROXY_AUTHENTICATION_FAILED = 0 ;
2016-09-09 16:09:51 -07:00
2016-10-20 19:15:09 -07:00
EWAPI Eina_Error EFL_NET_SERVER_ERROR_COULDNT_RESOLVE_HOST = 0 ;
2016-10-28 17:48:19 -07:00
EWAPI Eina_Error EFL_NET_SOCKET_SSL_ERROR_HANDSHAKE = 0 ;
EWAPI Eina_Error EFL_NET_SOCKET_SSL_ERROR_CERTIFICATE_VERIFY_FAILED = 0 ;
* 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
2016-10-20 19:15:09 -07:00
EFL_NET_SERVER_ERROR_COULDNT_RESOLVE_HOST = eina_error_msg_static_register ( " Couldn't resolve host name " ) ;
2016-10-28 17:48:19 -07:00
EFL_NET_SOCKET_SSL_ERROR_HANDSHAKE = eina_error_msg_static_register ( " Failed SSL handshake " ) ;
EFL_NET_SOCKET_SSL_ERROR_CERTIFICATE_VERIFY_FAILED = eina_error_msg_static_register ( " Failed to verify peer's certificate " ) ;
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
2016-10-27 04:01:19 -07:00
# ifndef _WIN32
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
2016-10-26 13:57:37 -07:00
efl_net_unix_fmt ( char * buf , size_t buflen , SOCKET fd , const struct sockaddr_un * addr , socklen_t addrlen )
{
const char * src = addr - > sun_path ;
socklen_t pathlen = addrlen - offsetof ( struct sockaddr_un , sun_path ) ;
if ( addr - > sun_family ! = AF_UNIX )
{
ERR ( " unsupported address family: %d " , addr - > sun_family ) ;
return EINA_FALSE ;
}
if ( addrlen = = offsetof ( struct sockaddr_un , sun_path ) )
{
2016-11-18 06:17:08 -08:00
int r = snprintf ( buf , buflen , " unnamed: " SOCKET_FMT , fd ) ;
2016-10-26 13:57:37 -07:00
if ( r < 0 )
{
ERR ( " snprintf(): %s " , strerror ( errno ) ) ;
return EINA_FALSE ;
}
else if ( ( size_t ) r > buflen )
{
ERR ( " buflen=%zu is too small, required=%d " , buflen , r ) ;
return EINA_FALSE ;
}
return EINA_TRUE ;
}
if ( src [ 0 ] ! = ' \0 ' )
{
if ( buflen < pathlen )
{
ERR ( " buflen=%zu is too small, required=%u " , buflen , pathlen ) ;
return EINA_FALSE ;
}
}
else
{
if ( buflen < pathlen + sizeof ( " abstract: " ) - 2 )
{
ERR ( " buflen=%zu is too small, required=%zu " , buflen , pathlen + sizeof ( " abstract: " ) - 2 ) ;
return EINA_FALSE ;
}
memcpy ( buf , " abstract: " , sizeof ( " abstract: " ) - 1 ) ;
buf + = sizeof ( " abstract: " ) - 1 ;
src + + ;
}
memcpy ( buf , src , pathlen ) ;
buf [ pathlen ] = ' \0 ' ;
return EINA_TRUE ;
}
2016-10-27 04:01:19 -07:00
# endif
2016-10-26 13:57:37 -07:00
Eina_Bool
efl_net_ip_port_fmt ( char * buf , size_t buflen , const struct sockaddr * addr )
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
{
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 ;
}
2016-10-26 13:57:37 -07:00
else if ( ( size_t ) r > buflen )
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
{
2016-10-26 13:57:37 -07:00
ERR ( " buffer is too small: %zu, required %d " , buflen , r ) ;
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
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 ;
}
2016-11-01 11:01:57 -07:00
# ifdef HAVE_SYSTEMD
Eina_Error
efl_net_ip_socket_activate_check ( const char * address , int family , int type , Eina_Bool * listening )
{
SOCKET fd = SD_LISTEN_FDS_START + sd_fd_index ;
int r ;
if ( sd_fd_index > = sd_fd_max ) return ENOENT ;
if ( family = = AF_UNIX )
{
char buf [ sizeof ( struct sockaddr_un ) ] = " " ;
const char * sun_path ;
size_t len ;
if ( strncmp ( address , " abstract: " , strlen ( " abstract: " ) ) = = 0 )
{
const char * path = address + strlen ( " abstract: " ) ;
if ( strlen ( path ) + 2 > sizeof ( buf ) )
{
ERR ( " abstract path is too long: %s " , path ) ;
return EINVAL ;
}
buf [ 0 ] = ' \0 ' ;
memcpy ( buf + 1 , path , strlen ( path ) + 1 ) ;
sun_path = buf ;
len = strlen ( path ) + 2 ;
}
else
{
if ( strlen ( address ) + 1 > sizeof ( buf ) )
{
ERR ( " path is too long: %s " , address ) ;
return EINVAL ;
}
sun_path = address ;
len = strlen ( address ) + 1 ;
}
r = sd_is_socket_unix ( fd , type , 0 , sun_path , len ) ;
if ( r < 0 )
{
2016-11-18 06:17:08 -08:00
ERR ( " socket " SOCKET_FMT " is not of family=%d, type=%d " , fd , family , type ) ;
2016-11-01 11:01:57 -07:00
return EINVAL ;
}
if ( listening ) * listening = ( r = = 1 ) ;
return 0 ;
}
else if ( ( family = = AF_UNSPEC ) | | ( family = = AF_INET ) | | ( family = = AF_INET6 ) )
{
char * str ;
const char * host , * port ;
struct sockaddr_storage sock_addr ;
struct sockaddr_storage want_addr = { . ss_family = family } ;
socklen_t addrlen ;
Eina_Error err ;
int x ;
r = sd_is_socket ( fd , family , type , ( type = = SOCK_DGRAM ) ? - 1 : 0 ) ;
if ( r < 0 )
{
2016-11-18 06:17:08 -08:00
ERR ( " socket " SOCKET_FMT " is not of family=%d, type=%d " , fd , family , type ) ;
2016-11-01 11:01:57 -07:00
return EINVAL ;
}
if ( ( type = = SOCK_DGRAM ) & & ( listening ) ) * listening = EINA_FALSE ;
else if ( listening ) * listening = ( r = = 1 ) ;
addrlen = sizeof ( sock_addr ) ;
if ( getsockname ( fd , ( struct sockaddr * ) & sock_addr , & addrlen ) ! = 0 )
{
err = efl_net_socket_error_get ( ) ;
2016-11-18 06:17:08 -08:00
ERR ( " could not query socket= " SOCKET_FMT " name: %s " , fd , eina_error_msg_get ( err ) ) ;
2016-11-01 11:01:57 -07:00
return err ;
}
str = strdup ( address ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( str , ENOMEM ) ;
if ( ! efl_net_ip_port_split ( str , & host , & port ) )
{
ERR ( " invalid IP:PORT address: %s " , address ) ;
free ( str ) ;
return EINVAL ;
}
if ( ! port ) port = " 0 " ;
if ( ( family = = AF_UNSPEC ) & & ( strchr ( host , ' : ' ) ) ) family = AF_INET6 ;
if ( family = = AF_INET6 )
{
struct sockaddr_in6 * a = ( struct sockaddr_in6 * ) & want_addr ;
x = inet_pton ( AF_INET6 , host , & a - > sin6_addr ) ;
}
else
{
struct sockaddr_in * a = ( struct sockaddr_in * ) & want_addr ;
x = inet_pton ( AF_INET , host , & a - > sin_addr ) ;
}
/* FAST PATH: numbers were provided */
if ( x = = 1 )
{
char * endptr ;
unsigned long p ;
Eina_Bool matches ;
want_addr . ss_family = family ;
if ( want_addr . ss_family ! = sock_addr . ss_family )
{
2016-11-18 06:17:08 -08:00
ERR ( " socket " SOCKET_FMT " family=%d differs from wanted %d " , fd , sock_addr . ss_family , want_addr . ss_family ) ;
2016-11-01 11:01:57 -07:00
free ( str ) ;
return EINVAL ;
}
errno = 0 ;
p = strtoul ( port , & endptr , 10 ) ;
if ( ( errno ) | | ( endptr = = port ) | | ( * endptr ! = ' \0 ' ) )
{
ERR ( " invalid port number '%s' " , port ) ;
free ( str ) ;
return EINVAL ;
}
else if ( p > UINT16_MAX )
{
ERR ( " invalid port number %lu (out of range) " , p ) ;
free ( str ) ;
return ERANGE ;
}
if ( family = = AF_INET6 )
{
struct sockaddr_in6 * a = ( struct sockaddr_in6 * ) & want_addr ;
a - > sin6_port = htons ( p ) ;
matches = memcmp ( a , & sock_addr , sizeof ( * a ) ) = = 0 ;
}
else
{
struct sockaddr_in * a = ( struct sockaddr_in * ) & want_addr ;
x = inet_pton ( AF_INET , host , & a - > sin_addr ) ;
a - > sin_port = htons ( p ) ;
matches = memcmp ( a , & sock_addr , sizeof ( * a ) ) = = 0 ;
}
if ( ! matches )
{
char buf [ INET6_ADDRSTRLEN + sizeof ( " []:65536 " ) ] = " " ;
efl_net_ip_port_fmt ( buf , sizeof ( buf ) , ( struct sockaddr * ) & sock_addr ) ;
2016-11-18 06:17:08 -08:00
ERR ( " socket " SOCKET_FMT " address %s differs from wanted %s " , fd , buf , address ) ;
2016-11-01 11:01:57 -07:00
free ( str ) ;
return EINVAL ;
}
free ( str ) ;
return 0 ;
}
else
{
/*
* NOTE : this may block , but users should be using the IP : PORT
* as numbers , getting into the fast path above .
*
* This is best - try to help API to be usable , but may
* impact the main loop execution for a while . However
* people doing bind are expected to do so on a local
* address , usually resolves faster without too many DNS
* lookups .
*/
struct addrinfo hints = {
. ai_socktype = type ,
. ai_family = family ,
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
} ;
struct addrinfo * results , * itr ;
DBG ( " resolving '%s', it may block main loop! Consider using IP:PORT " , address ) ;
do
{
x = getaddrinfo ( host , port , & hints , & results ) ;
}
while ( ( r = = EAI_AGAIN ) | | ( ( r = = EAI_SYSTEM ) & & ( errno = = EINTR ) ) ) ;
if ( x ! = 0 )
{
ERR ( " couldn't resolve host='%s', port='%s': %s " ,
host , port , gai_strerror ( x ) ) ;
free ( str ) ;
return EINVAL ;
}
err = EINVAL ;
for ( itr = results ; itr ! = NULL ; itr = itr - > ai_next )
{
if ( sock_addr . ss_family ! = itr - > ai_family ) continue ;
if ( memcmp ( itr - > ai_addr , & sock_addr , itr - > ai_addrlen ) = = 0 )
{
err = 0 ;
break ;
}
}
freeaddrinfo ( results ) ;
free ( str ) ;
return err ;
}
}
else
{
if ( listening ) * listening = EINA_FALSE ;
ERR ( " unsupported family=%d " , family ) ;
return EINVAL ;
}
}
# endif
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 )
{
2016-10-22 16:49:01 -07:00
SOCKET * p_fd = data ;
SOCKET fd = * p_fd ;
2016-10-22 08:15:16 -07:00
* p_fd = INVALID_SOCKET ;
2016-10-22 16:49:01 -07:00
if ( fd ! = INVALID_SOCKET ) closesocket ( fd ) ;
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
}
2016-09-09 16:09:51 -07:00
2016-10-22 16:49:01 -07:00
SOCKET
2016-08-24 08:34:59 -07:00
efl_net_socket4 ( int domain , int type , int protocol , Eina_Bool close_on_exec )
{
2016-10-22 16:49:01 -07:00
SOCKET fd = INVALID_SOCKET ;
2016-08-24 08:34:59 -07:00
# ifdef SOCK_CLOEXEC
if ( close_on_exec ) type | = SOCK_CLOEXEC ;
# endif
fd = socket ( domain , type , protocol ) ;
2016-10-22 08:15:16 -07:00
# if !defined(SOCK_CLOEXEC) && defined(FD_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 ) ;
2016-10-22 08:15:16 -07:00
if ( fd ! = INVALID_SOCKET )
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 ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( fd ) ;
2016-10-22 08:15:16 -07:00
fd = INVALID_SOCKET ;
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
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
2016-10-20 19:15:09 -07:00
typedef struct _Efl_Net_Ip_Resolve_Async_Data
{
Efl_Net_Ip_Resolve_Async_Cb cb ;
const void * data ;
char * host ;
char * port ;
struct addrinfo * result ;
struct addrinfo * hints ;
int gai_error ;
} Efl_Net_Ip_Resolve_Async_Data ;
static void
_efl_net_ip_resolve_async_run ( void * data , Ecore_Thread * thread EINA_UNUSED )
{
Efl_Net_Ip_Resolve_Async_Data * d = data ;
/* allows ecore_thread_cancel() to cancel at some points, see
* man : pthreads ( 7 ) .
*
* no need to set cleanup functions since the main thread will
* handle that with _efl_net_ip_resolve_async_cancel ( ) .
*/
eina_thread_cancellable_set ( EINA_TRUE , NULL ) ;
while ( EINA_TRUE )
{
DBG ( " resolving host='%s' port='%s' " , d - > host , d - > port ) ;
d - > gai_error = getaddrinfo ( d - > host , d - > port , d - > hints , & d - > result ) ;
if ( d - > gai_error = = 0 ) break ;
if ( d - > gai_error = = EAI_AGAIN ) continue ;
if ( ( d - > gai_error = = EAI_SYSTEM ) & & ( errno = = EINTR ) ) continue ;
DBG ( " getaddrinfo( \" %s \" , \" %s \" ) failed: %s " , d - > host , d - > port , gai_strerror ( d - > gai_error ) ) ;
break ;
}
eina_thread_cancellable_set ( EINA_FALSE , NULL ) ;
if ( eina_log_domain_level_check ( _ecore_con_log_dom , EINA_LOG_LEVEL_DBG ) )
{
char buf [ INET6_ADDRSTRLEN + sizeof ( " []:65536 " ) ] = " " ;
const struct addrinfo * addrinfo ;
for ( addrinfo = d - > result ; addrinfo ! = NULL ; addrinfo = addrinfo - > ai_next )
{
if ( efl_net_ip_port_fmt ( buf , sizeof ( buf ) , addrinfo - > ai_addr ) )
DBG ( " resolved host='%s' port='%s': %s " , d - > host , d - > port , buf ) ;
}
}
}
static void
_efl_net_ip_resolve_async_data_free ( Efl_Net_Ip_Resolve_Async_Data * d )
{
free ( d - > hints ) ;
free ( d - > host ) ;
free ( d - > port ) ;
free ( d ) ;
}
static void
_efl_net_ip_resolve_async_end ( void * data , Ecore_Thread * thread EINA_UNUSED )
{
Efl_Net_Ip_Resolve_Async_Data * d = data ;
d - > cb ( ( void * ) d - > data , d - > host , d - > port , d - > hints , d - > result , d - > gai_error ) ;
_efl_net_ip_resolve_async_data_free ( d ) ;
}
static void
_efl_net_ip_resolve_async_cancel ( void * data , Ecore_Thread * thread EINA_UNUSED )
{
Efl_Net_Ip_Resolve_Async_Data * d = data ;
if ( d - > result ) freeaddrinfo ( d - > result ) ;
_efl_net_ip_resolve_async_data_free ( d ) ;
}
Ecore_Thread *
efl_net_ip_resolve_async_new ( const char * host , const char * port , const struct addrinfo * hints , Efl_Net_Ip_Resolve_Async_Cb cb , const void * data )
{
Efl_Net_Ip_Resolve_Async_Data * d ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( host , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( port , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( cb , NULL ) ;
d = malloc ( sizeof ( Efl_Net_Ip_Resolve_Async_Data ) ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( d , NULL ) ;
d - > cb = cb ;
d - > data = data ;
d - > host = strdup ( host ) ;
EINA_SAFETY_ON_NULL_GOTO ( d - > host , failed_host ) ;
d - > port = strdup ( port ) ;
EINA_SAFETY_ON_NULL_GOTO ( d - > port , failed_port ) ;
if ( ! hints ) d - > hints = NULL ;
else
{
d - > hints = malloc ( sizeof ( struct addrinfo ) ) ;
EINA_SAFETY_ON_NULL_GOTO ( d - > hints , failed_hints ) ;
memcpy ( d - > hints , hints , sizeof ( struct addrinfo ) ) ;
}
d - > result = NULL ;
return ecore_thread_run ( _efl_net_ip_resolve_async_run ,
_efl_net_ip_resolve_async_end ,
_efl_net_ip_resolve_async_cancel ,
d ) ;
failed_hints :
free ( d - > port ) ;
failed_port :
free ( d - > host ) ;
failed_host :
free ( d ) ;
return 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
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 ;
2016-10-22 16:49:01 -07:00
SOCKET 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
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 ;
2016-11-18 06:32:16 -08:00
char buf [ INET6_ADDRSTRLEN + sizeof ( " []:65536 " )
# ifndef _WIN32
+ sizeof ( struct sockaddr_un )
# endif
] = " " ;
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 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 ) ;
2016-10-22 08:15:16 -07:00
if ( d - > sockfd = = INVALID_SOCKET )
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
{
2016-10-22 08:15:16 -07:00
d - > error = efl_net_socket_error_get ( ) ;
DBG ( " socket(%d, %d, %d) failed: %s " , d - > addr - > sa_family , d - > type , d - > protocol , eina_error_msg_get ( d - > 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
return ;
2016-09-09 16:09:51 -07:00
}
if ( eina_log_domain_level_check ( _ecore_con_log_dom , EINA_LOG_LEVEL_DBG ) )
2016-10-26 13:57:37 -07:00
{
2016-10-27 04:01:19 -07:00
# ifndef _WIN32
2016-10-26 13:57:37 -07:00
if ( d - > addr - > sa_family = = AF_UNIX )
efl_net_unix_fmt ( buf , sizeof ( buf ) , d - > sockfd , ( const struct sockaddr_un * ) d - > addr , d - > addrlen ) ;
else
2016-10-27 04:01:19 -07:00
# endif
2016-10-26 13:57:37 -07:00
efl_net_ip_port_fmt ( buf , sizeof ( buf ) , d - > addr ) ;
}
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
2016-11-18 06:17:08 -08:00
DBG ( " connecting fd= " SOCKET_FMT " to %s " , d - > sockfd , buf ) ;
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
r = connect ( d - > sockfd , d - > addr , d - > addrlen ) ;
2016-10-22 08:15:16 -07:00
if ( r ! = 0 )
2016-09-09 16:09:51 -07:00
{
2016-10-22 16:49:01 -07:00
SOCKET fd = d - > sockfd ;
2016-10-22 08:15:16 -07:00
d - > error = efl_net_socket_error_get ( ) ;
d - > sockfd = INVALID_SOCKET ;
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
/* close() is a cancellation point, thus unset sockfd before
* closing , so the main thread _efl_net_connect_async_cancel ( )
* won ' t close it again .
*/
2016-10-22 16:49:01 -07:00
closesocket ( fd ) ;
2016-11-18 06:17:08 -08:00
DBG ( " connect( " SOCKET_FMT " , %s) failed: %s " , fd , buf , eina_error_msg_get ( d - > 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
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
2016-11-18 06:17:08 -08:00
DBG ( " connected fd= " SOCKET_FMT " 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 */
2016-10-22 08:15:16 -07:00
if ( ( ! d - > close_on_exec ) & & ( d - > sockfd ! = INVALID_SOCKET ) )
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 flags = fcntl ( d - > sockfd , F_GETFD ) ;
if ( flags < 0 )
{
d - > error = errno ;
2016-11-18 06:17:08 -08:00
ERR ( " fcntl( " SOCKET_FMT " , F_GETFD): %s " , d - > sockfd , eina_error_msg_get ( d - > error ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( d - > sockfd ) ;
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
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
{
flags & = ( ~ FD_CLOEXEC ) ;
if ( fcntl ( d - > sockfd , F_SETFD , flags ) < 0 )
{
d - > error = errno ;
2016-11-18 06:17:08 -08:00
ERR ( " fcntl( " SOCKET_FMT " , F_SETFD, %#x): %s " , d - > sockfd , flags , eina_error_msg_get ( d - > error ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( d - > sockfd ) ;
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
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
}
}
}
# 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 ;
2016-10-22 16:49:01 -07:00
if ( d - > sockfd ! = INVALID_SOCKET ) closesocket ( 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_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
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
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 ;
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 ;
2016-10-22 16:49:01 -07:00
SOCKET sockfd ;
2016-09-09 16:09:51 -07:00
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
2016-11-18 06:17:08 -08:00
_efl_net_ip_connect ( const struct addrinfo * addr , SOCKET * 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
{
2016-10-22 16:49:01 -07:00
SOCKET fd = INVALID_SOCKET ;
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_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 ) ;
2016-10-22 08:15:16 -07:00
if ( fd = = INVALID_SOCKET ) ret = efl_net_socket_error_get ( ) ;
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
{
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 ) )
2016-11-18 06:17:08 -08:00
DBG ( " connect fd= " SOCKET_FMT " to %s " , fd , buf ) ;
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
}
r = connect ( fd , addr - > ai_addr , addr - > ai_addrlen ) ;
if ( r = = 0 )
{
2016-11-18 06:17:08 -08:00
DBG ( " connected fd= " SOCKET_FMT " to %s " , fd , buf ) ;
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
* sockfd = fd ;
}
else
{
2016-10-22 08:15:16 -07:00
ret = efl_net_socket_error_get ( ) ;
2016-11-18 06:17:08 -08:00
DBG ( " couldn't connect fd= " SOCKET_FMT " to %s: %s " , fd , buf , eina_error_msg_get ( ret ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( fd ) ;
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 sockfd on success */
}
return ret ;
}
static Eina_Error
2016-11-18 06:17:08 -08:00
_efl_net_ip_resolve_and_connect ( const char * host , const char * port , int type , int protocol , SOCKET * sockfd , struct sockaddr * addr , socklen_t * p_addrlen )
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
{
struct addrinfo * results = NULL ;
struct addrinfo hints = {
. ai_socktype = type ,
. ai_protocol = protocol ,
. ai_family = AF_UNSPEC ,
2016-10-22 04:41:26 -07:00
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
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_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 ;
2016-10-22 08:15:16 -07:00
* sockfd = INVALID_SOCKET ;
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
{
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 ;
2016-10-22 16:49:01 -07:00
SOCKET fd ;
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_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 ) )
2016-11-18 06:17:08 -08:00
DBG ( " resolved address='%s' to %s. Connect using fd= " SOCKET_FMT " socks4://%s:%s " , d - > address , buf , fd , proxy_host , proxy_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
}
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 )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't request connection to host=%s fd= " SOCKET_FMT " socks4://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv reply of connection to host=%s fd= " SOCKET_FMT " socks4://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( reply ) , s ) ;
}
else
{
if ( reply . status ! = EFL_NET_SOCKS4_REPLY_STATUS_GRANTED )
2016-11-18 06:17:08 -08:00
DBG ( " rejected connection to host=%s fd= " SOCKET_FMT " socks4://%s:%s: reason=%#x " , buf , fd , proxy_host , proxy_port , reply . status ) ;
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
{
memcpy ( & d - > addr , addrinfo - > ai_addr , addrinfo - > ai_addrlen ) ;
d - > addrlen = addrinfo - > ai_addrlen ;
d - > sockfd = fd ;
d - > error = 0 ;
ret = EINA_TRUE ;
2016-11-18 06:17:08 -08:00
DBG ( " connected to host=%s fd= " SOCKET_FMT " socks4://%s:%s " , buf , fd , proxy_host , proxy_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
}
}
}
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-10-22 04:41:26 -07:00
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
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
} ;
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 )
{
2016-10-22 16:49:01 -07:00
SOCKET fd = INVALID_SOCKET ;
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 * 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 ,
2016-10-22 04:41:26 -07:00
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
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 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 ;
}
2016-11-18 06:17:08 -08:00
DBG ( " connected fd= " SOCKET_FMT " to socks4a://%s " , fd , 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
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 )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
DBG ( " couldn't send proxy request: %s " , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
DBG ( " couldn't recv proxy reply: %s " , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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) */
}
2016-11-18 06:17:08 -08:00
EINA_THREAD_CLEANUP_POP ( d - > sockfd = = INVALID_SOCKET ) ; /* we need fd only on success */
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
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
2016-10-22 16:49:01 -07:00
_efl_net_ip_connect_async_run_socks5_auth_user_pass ( SOCKET fd , const char * user , const char * pass , const char * proxy_protocol , const char * proxy_host , const char * proxy_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
{
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 )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't send user-password authentication to fd= " SOCKET_FMT " %s://%s:%s: %s " , fd , proxy_protocol , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv user-password authentication reply from fd= " SOCKET_FMT " %s://%s:%s: %s " , fd , proxy_protocol , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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
{
2016-11-18 06:17:08 -08:00
DBG ( " successfully authenticated user=%s with proxy fd= " SOCKET_FMT " %s://%s:%s " , user , fd , proxy_protocol , proxy_host , proxy_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
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 ;
2016-10-22 16:49:01 -07:00
SOCKET fd ;
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_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 ) )
2016-11-18 06:17:08 -08:00
DBG ( " resolved address='%s' to %s. Connect using fd= " SOCKET_FMT " socks5://%s:%s " , d - > address , buf , fd , proxy_host , proxy_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
}
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't request connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv greeting reply of connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( greeting_reply ) , s ) ;
}
else
{
if ( greeting_reply . auth ! = greeting . auths [ 0 ] )
2016-11-18 06:17:08 -08:00
DBG ( " proxy server rejected authentication %#x trying connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s " , greeting . auths [ 0 ] , buf , fd , proxy_host , proxy_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
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 )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't request connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv reply of connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( reply ) , s ) ;
}
else
{
if ( reply . base . status ! = EFL_NET_SOCKS5_REPLY_STATUS_GRANTED )
2016-11-18 06:17:08 -08:00
DBG ( " rejected IPv4 connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: reason=%#x " , buf , fd , proxy_host , proxy_port , reply . base . status ) ;
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
{
memcpy ( & d - > addr , addrinfo - > ai_addr , addrinfo - > ai_addrlen ) ;
d - > addrlen = addrinfo - > ai_addrlen ;
d - > sockfd = fd ;
d - > error = 0 ;
ret = EINA_TRUE ;
2016-11-18 06:17:08 -08:00
DBG ( " connected IPv4 to host=%s fd= " SOCKET_FMT " socks5://%s:%s " , buf , fd , proxy_host , proxy_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
}
}
}
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv reply of connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: %s " , buf , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( reply ) , s ) ;
}
else
{
if ( reply . base . status ! = EFL_NET_SOCKS5_REPLY_STATUS_GRANTED )
2016-11-18 06:17:08 -08:00
DBG ( " rejected IPv6 connection to host=%s fd= " SOCKET_FMT " socks5://%s:%s: reason=%#x " , buf , fd , proxy_host , proxy_port , reply . base . status ) ;
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
{
memcpy ( & d - > addr , addrinfo - > ai_addr , addrinfo - > ai_addrlen ) ;
d - > addrlen = addrinfo - > ai_addrlen ;
d - > sockfd = fd ;
d - > error = 0 ;
ret = EINA_TRUE ;
2016-11-18 06:17:08 -08:00
DBG ( " connected IPv6 to host=%s fd= " SOCKET_FMT " socks5://%s:%s " , buf , fd , proxy_host , proxy_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
}
}
}
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 ,
2016-10-22 04:41:26 -07:00
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
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_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 )
{
2016-10-22 16:49:01 -07:00
SOCKET fd = INVALID_SOCKET ;
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 * 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 ;
}
2016-11-18 06:17:08 -08:00
DBG ( " connected fd= " SOCKET_FMT " to socks5h://%s " , fd , 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
EINA_THREAD_CLEANUP_PUSH ( _cleanup_close , & fd ) ;
s = send ( fd , & greeting , sizeof ( greeting ) , MSG_NOSIGNAL ) ;
if ( s ! = ( ssize_t ) sizeof ( greeting ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't request connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv greeting reply of connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( greeting_reply ) , s ) ;
}
else
{
if ( greeting_reply . auth ! = greeting . auths [ 0 ] )
2016-11-18 06:17:08 -08:00
DBG ( " proxy server rejected authentication %#x trying connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s " , greeting . auths [ 0 ] , host , port , fd , proxy_host , proxy_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
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 ,
2016-10-22 04:41:26 -07:00
. ai_flags = AI_ADDRCONFIG | AI_V4MAPPED ,
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 , ' : ' ) ) 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 )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't request connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv reply of connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
DBG ( " couldn't recv proxy reply: need %zu, did %zd " , sizeof ( reply ) , s ) ;
}
else
{
if ( reply . status ! = EFL_NET_SOCKS5_REPLY_STATUS_GRANTED )
2016-11-18 06:17:08 -08:00
DBG ( " rejected connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: reason=%#x " , host , port , fd , proxy_host , proxy_port , reply . status ) ;
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 ( 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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv ipv4 of connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ;
2016-11-18 06:17:08 -08:00
DBG ( " connected IPv4 to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s " , host , port , fd , proxy_host , proxy_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
}
}
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 ) )
{
2016-10-22 08:15:16 -07:00
if ( s = = SOCKET_ERROR )
2016-11-18 06:17:08 -08:00
DBG ( " couldn't recv ipv6 of connection to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s: %s " , host , port , fd , proxy_host , proxy_port , eina_error_msg_get ( efl_net_socket_error_get ( ) ) ) ;
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
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 ;
2016-11-18 06:17:08 -08:00
DBG ( " connected IPv6 to host=%s:%s fd= " SOCKET_FMT " socks5h://%s:%s " , host , port , fd , proxy_host , proxy_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
}
}
else
{
/* most proxy servers will return a failure instead of this, but let's guard and log */
2016-11-18 06:17:08 -08:00
DBG ( " couldn't resolve host %s:%s fd= " SOCKET_FMT " socks5h://%s:%s " , host , port , fd , proxy_host , proxy_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
}
}
}
EINA_THREAD_CLEANUP_POP ( EINA_TRUE ) ; /* free(request) */
break ;
}
}
EINA_THREAD_CLEANUP_POP ( EINA_TRUE ) ; /* freeaddrinfo(results) */
}
}
}
}
}
2016-11-18 06:17:08 -08:00
EINA_THREAD_CLEANUP_POP ( d - > sockfd = = INVALID_SOCKET ) ; /* we need fd only on success */
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
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 .
*/
2016-09-20 16:13:25 -07:00
Eina_Stringshare * url ;
2016-09-18 23:19:16 -07:00
2016-09-20 16:13:25 -07:00
url = eina_stringshare_printf ( " %s://%s:%s " , d - > protocol = = IPPROTO_UDP ? " udp " : " tcp " , host , port ) ;
if ( ! url )
{
ERR ( " Could not assemble URL " ) ;
}
else
{
proxies = ecore_con_libproxy_proxies_get ( url ) ;
eina_stringshare_del ( url ) ;
}
2016-09-18 23:19:16 -07:00
}
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 */
2016-10-22 08:15:16 -07:00
if ( ( ! d - > close_on_exec ) & & ( d - > sockfd ! = INVALID_SOCKET ) )
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 flags = fcntl ( d - > sockfd , F_GETFD ) ;
if ( flags < 0 )
{
d - > error = errno ;
2016-11-18 06:17:08 -08:00
ERR ( " fcntl( " SOCKET_FMT " , F_GETFD): %s " , d - > sockfd , strerror ( errno ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( d - > sockfd ) ;
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
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
{
flags & = ( ~ FD_CLOEXEC ) ;
if ( fcntl ( d - > sockfd , F_SETFD , flags ) < 0 )
{
d - > error = errno ;
2016-11-18 06:17:08 -08:00
ERR ( " fcntl( " SOCKET_FMT " , F_SETFD, %#x): %s " , d - > sockfd , flags , strerror ( errno ) ) ;
2016-10-22 16:49:01 -07:00
closesocket ( d - > sockfd ) ;
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
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
}
}
}
# 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-10-22 16:49:01 -07:00
if ( d - > sockfd ! = INVALID_SOCKET ) closesocket ( 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 ;
2016-10-22 08:15:16 -07:00
d - > sockfd = INVALID_SOCKET ;
2016-09-09 16:09:51 -07:00
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
2016-10-25 05:03:34 -07:00
static Eina_Error
efl_net_multicast_address4_parse ( const char * address , struct ip_mreq * mreq )
{
char * str = NULL ;
const char * iface ;
Eina_Error err = 0 ;
int r ;
iface = strchr ( address , ' @ ' ) ;
if ( ! iface ) iface = " 0.0.0.0 " ;
else
{
str = malloc ( iface - address + 1 ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( str , ENOMEM ) ;
memcpy ( str , address , iface - address ) ;
str [ iface - address ] = ' \0 ' ;
address = str ;
iface + + ;
if ( iface [ 0 ] = = ' \0 ' ) iface = " 0.0.0.0 " ;
}
if ( address [ 0 ] = = ' \0 ' )
{
err = EINVAL ;
goto end ;
}
r = inet_pton ( AF_INET , address , & mreq - > imr_multiaddr ) ;
if ( r ! = 1 )
{
if ( r < 0 ) err = efl_net_socket_error_get ( ) ;
else err = EINVAL ;
goto end ;
}
r = inet_pton ( AF_INET , iface , & mreq - > imr_interface ) ;
if ( r ! = 1 )
{
if ( r < 0 ) err = efl_net_socket_error_get ( ) ;
else err = EINVAL ;
goto end ;
}
end :
free ( str ) ;
return err ;
}
static Eina_Error
efl_net_multicast_address6_parse ( const char * address , struct ipv6_mreq * mreq )
{
char * str ;
char * endptr ;
const char * iface ;
Eina_Error err = 0 ;
unsigned long idx ;
int r ;
str = strdup ( address ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( str , ENOMEM ) ;
address = str ;
if ( address [ 0 ] = = ' [ ' )
{
address + + ;
endptr = strchr ( address , ' ] ' ) ;
if ( ! endptr )
{
err = EINVAL ;
goto end ;
}
memmove ( endptr , endptr + 1 , strlen ( endptr + 1 ) + 1 ) ;
}
iface = strchr ( address , ' @ ' ) ;
if ( ! iface ) iface = " 0 " ;
else
{
str [ iface - address ] = ' \0 ' ;
iface + + ;
if ( iface [ 0 ] = = ' \0 ' ) iface = " 0 " ;
}
if ( address [ 0 ] = = ' \0 ' )
{
err = EINVAL ;
goto end ;
}
r = inet_pton ( AF_INET6 , address , & mreq - > ipv6mr_multiaddr ) ;
if ( r ! = 1 )
{
if ( r < 0 ) err = efl_net_socket_error_get ( ) ;
else err = EINVAL ;
goto end ;
}
errno = 0 ;
idx = strtoul ( iface , & endptr , 10 ) ;
if ( errno )
{
err = errno ;
goto end ;
}
else if ( ( iface = = endptr ) | | ( endptr [ 0 ] ! = ' \0 ' ) )
{
errno = EINVAL ;
goto end ;
}
else if ( idx > UINT32_MAX )
{
errno = ERANGE ;
goto end ;
}
mreq - > ipv6mr_interface = idx ;
end :
free ( str ) ;
return err ;
}
Eina_Error
efl_net_multicast_join ( SOCKET fd , int family , const char * address )
{
Eina_Error err ;
if ( family = = AF_INET )
{
struct ip_mreq mreq ;
err = efl_net_multicast_address4_parse ( address , & mreq ) ;
if ( err )
return err ;
if ( setsockopt ( fd , IPPROTO_IP , IP_ADD_MEMBERSHIP , & mreq , sizeof ( mreq ) ) = = 0 )
return 0 ;
}
else if ( family = = AF_INET6 )
{
struct ipv6_mreq mreq ;
err = efl_net_multicast_address6_parse ( address , & mreq ) ;
if ( err )
return err ;
2016-10-25 14:32:07 -07:00
if ( setsockopt ( fd , IPPROTO_IPV6 , IPV6_JOIN_GROUP , & mreq , sizeof ( mreq ) ) = = 0 )
2016-10-25 05:03:34 -07:00
return 0 ;
}
else
{
ERR ( " invalid socket family=%d " , family ) ;
return EINVAL ;
}
return efl_net_socket_error_get ( ) ;
}
Eina_Error
efl_net_multicast_leave ( SOCKET fd , int family , const char * address )
{
Eina_Error err ;
if ( family = = AF_INET )
{
struct ip_mreq mreq ;
err = efl_net_multicast_address4_parse ( address , & mreq ) ;
if ( err )
return err ;
if ( setsockopt ( fd , IPPROTO_IP , IP_DROP_MEMBERSHIP , & mreq , sizeof ( mreq ) ) = = 0 )
return 0 ;
}
else if ( family = = AF_INET6 )
{
struct ipv6_mreq mreq ;
err = efl_net_multicast_address6_parse ( address , & mreq ) ;
if ( err )
return err ;
2016-10-25 14:32:07 -07:00
if ( setsockopt ( fd , IPPROTO_IPV6 , IPV6_LEAVE_GROUP , & mreq , sizeof ( mreq ) ) = = 0 )
2016-10-25 05:03:34 -07:00
return 0 ;
}
else
{
ERR ( " invalid socket family=%d " , family ) ;
return EINVAL ;
}
return efl_net_socket_error_get ( ) ;
}
Eina_Error
efl_net_multicast_ttl_set ( SOCKET fd , int family , uint8_t ttl )
{
int level = ( family = = AF_INET ) ? IPPROTO_IP : IPPROTO_IPV6 ;
int opt = ( family = = AF_INET ) ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS ;
# ifdef _WIN32
DWORD value = ttl ;
# else
int value = ttl ;
# endif
if ( setsockopt ( fd , level , opt , & value , sizeof ( value ) ) = = 0 )
return 0 ;
return efl_net_socket_error_get ( ) ;
}
Eina_Error
efl_net_multicast_ttl_get ( SOCKET fd , int family , uint8_t * ttl )
{
int level = ( family = = AF_INET ) ? IPPROTO_IP : IPPROTO_IPV6 ;
int opt = ( family = = AF_INET ) ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS ;
# ifdef _WIN32
DWORD value ;
int valuelen = sizeof ( value ) ;
# else
int value ;
socklen_t valuelen = sizeof ( value ) ;
# endif
if ( getsockopt ( fd , level , opt , & value , & valuelen ) = = 0 )
{
* ttl = value ;
return 0 ;
}
return efl_net_socket_error_get ( ) ;
}
Eina_Error
efl_net_multicast_loopback_set ( SOCKET fd , int family , Eina_Bool loopback )
{
int level = ( family = = AF_INET ) ? IPPROTO_IP : IPPROTO_IPV6 ;
int opt = ( family = = AF_INET ) ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP ;
# ifdef _WIN32
DWORD value = loopback ;
# else
int value = loopback ;
# endif
if ( setsockopt ( fd , level , opt , & value , sizeof ( value ) ) = = 0 )
return 0 ;
return efl_net_socket_error_get ( ) ;
}
Eina_Error
efl_net_multicast_loopback_get ( SOCKET fd , int family , Eina_Bool * loopback )
{
int level = ( family = = AF_INET ) ? IPPROTO_IP : IPPROTO_IPV6 ;
int opt = ( family = = AF_INET ) ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP ;
# ifdef _WIN32
DWORD value ;
int valuelen = sizeof ( value ) ;
# else
int value ;
socklen_t valuelen = sizeof ( value ) ;
# endif
if ( getsockopt ( fd , level , opt , & value , & valuelen ) = = 0 )
{
* loopback = ! ! value ;
return 0 ;
}
return efl_net_socket_error_get ( ) ;
}
size_t
efl_net_udp_datagram_size_query ( SOCKET fd )
{
# ifdef _WIN32
unsigned long size ;
if ( ioctlsocket ( fd , FIONREAD , & size ) = = 0 )
return size ;
# else
int size ;
if ( ioctl ( fd , FIONREAD , & size ) = = 0 )
return size ;
# endif
return READBUFSIZ ;
}
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 ) ;
}