2011-12-04 Mike Blumenkrantz
* added ecore_timer_reset()
+
+2011-12-05 Mike Blumenkrantz
+
+ * added ecore_con_socks api
Additions:
* ecore
- ecore_timer_reset()
+ * ecore_con
+ - ecore_con_socks api
* ecore_x:
- ecore_x_randr_output_backlight_available()
# ecore_con
-AC_CHECK_HEADERS([arpa/inet.h arpa/nameser.h netinet/tcp.h netinet/in.h sys/socket.h sys/un.h ws2tcpip.h netdb.h])
+AC_CHECK_HEADERS([arpa/inet.h arpa/nameser.h netinet/tcp.h net/if.h netinet/in.h sys/socket.h sys/un.h ws2tcpip.h netdb.h])
if test "x${ac_cv_header_netdb_h}" = "xyes" ; then
have_addrinfo="yes"
typedef struct _Ecore_Con_Client Ecore_Con_Client;
/**
+ * @typedef Ecore_Con_Socks
+ * An object representing a SOCKS proxy
+ * @ingroup Ecore_Con_Socks_Group
+ */
+typedef struct Ecore_Con_Socks Ecore_Con_Socks;
+
+/**
* @typedef Ecore_Con_Url
* A handle to an http upload/download object
* @ingroup Ecore_Con_Url_Group
typedef struct _Ecore_Con_Event_Server_Write Ecore_Con_Event_Server_Write;
/**
+ * @typedef Ecore_Con_Event_Proxy_Bind
+ * Used as the @p data param for the corresponding event
+ * @since 1.2
+ */
+typedef struct _Ecore_Con_Event_Proxy_Bind Ecore_Con_Event_Proxy_Bind;
+
+/**
* @typedef Ecore_Con_Event_Url_Data
* Used as the @p data param for the corresponding event
* @ingroup Ecore_Con_Url_Group
};
/**
+ * @struct _Ecore_Con_Event_Proxy_Bind
+ * Used as the @p data param for the @ref ECORE_CON_EVENT_PROXY_BIND event
+ * @ingroup Ecore_Con_Socks_Group
+ */
+struct _Ecore_Con_Event_Proxy_Bind
+{
+ Ecore_Con_Server *server; /**< the server object connected to the proxy */
+ const char *ip; /**< the proxy-bound ip address */
+ int port; /**< the proxy-bound port */
+};
+
+/**
* @struct _Ecore_Con_Event_Url_Data
* Used as the @p data param for the @ref ECORE_CON_EVENT_URL_DATA event
* @ingroup Ecore_Con_Url_Group
EAPI extern int ECORE_CON_EVENT_CLIENT_DATA;
/** A server connection object has data */
EAPI extern int ECORE_CON_EVENT_SERVER_DATA;
+/** A server connection has successfully negotiated an ip:port binding
+ * @since 1.2
+ */
+EAPI extern int ECORE_CON_EVENT_PROXY_BIND;
/** A URL object has data */
EAPI extern int ECORE_CON_EVENT_URL_DATA;
/** A URL object has completed its transfer to and from the server and can be reused */
* @}
*/
+EAPI Ecore_Con_Socks *ecore_con_socks4_remote_add(const char *ip, int port, const char *username);
+EAPI void ecore_con_socks4_lookup_set(Ecore_Con_Socks *ecs, Eina_Bool enable);
+EAPI Eina_Bool ecore_con_socks4_lookup_get(Ecore_Con_Socks *ecs);
+EAPI Eina_Bool ecore_con_socks4_remote_exists(const char *ip, int port, const char *username);
+EAPI void ecore_con_socks4_remote_del(const char *ip, int port, const char *username);
+EAPI void ecore_con_socks_bind_set(Ecore_Con_Socks *ecs, Eina_Bool is_bind);
+EAPI Eina_Bool ecore_con_socks_bind_get(Ecore_Con_Socks *ecs);
+EAPI unsigned int ecore_con_socks_version_get(Ecore_Con_Socks *ecs);
+EAPI void ecore_con_socks_remote_del(Ecore_Con_Socks *ecs);
+EAPI void ecore_con_socks_apply_once(Ecore_Con_Socks *ecs);
+EAPI void ecore_con_socks_apply_always(Ecore_Con_Socks *ecs);
+
/**
* @defgroup Ecore_Con_Server_Group Ecore Connection Server Functions
*
*/
EAPI int ecore_con_client_port_get(Ecore_Con_Client *cl);
+
+
/**
* @}
*/
libecore_con_la_SOURCES = \
ecore_con.c \
+ecore_con_socks.c \
ecore_con_ssl.c \
ecore_con_url.c \
ecore_con_alloc.c
EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
+EAPI int ECORE_CON_EVENT_PROXY_BIND = 0;
static Eina_List *servers = NULL;
static int _ecore_con_init_count = 0;
static int _ecore_con_event_count = 0;
int _ecore_con_log_dom = -1;
+Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
+Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
EAPI int
ecore_con_init(void)
ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
+ ECORE_CON_EVENT_PROXY_BIND = ecore_event_type_new();
eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
/* TODO Remember return value, if it fails, use gethostbyname() */
+ ecore_con_socks_init();
ecore_con_ssl_init();
ecore_con_info_init();
_ecore_con_server_free(svr);
}
+ ecore_con_socks_shutdown();
if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
ecore_con_info_shutdown();
svr->reject_excess_clients = EINA_FALSE;
svr->clients = NULL;
svr->client_limit = -1;
- if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL))
- goto error;
type = compl_type & ECORE_CON_TYPE;
+ if (type > ECORE_CON_LOCAL_ABSTRACT)
+ {
+ /* never use proxies on local connections */
+ if (_ecore_con_proxy_once)
+ svr->ecs = _ecore_con_proxy_once;
+ else if (_ecore_con_proxy_global)
+ svr->ecs = _ecore_con_proxy_global;
+ _ecore_con_proxy_once = NULL;
+ if (svr->ecs)
+ {
+ if ((!svr->ecs->lookup) &&
+ (!ecore_con_lookup(svr->name, (Ecore_Con_Dns_Cb)ecore_con_socks_dns_cb, svr)))
+ goto error;
+ if (svr->ecs->lookup)
+ svr->ecs_state = ECORE_CON_SOCKS_STATE_RESOLVED;
+ }
+
+ }
+ if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL))
+ goto error;
+
if (((type == ECORE_CON_REMOTE_TCP) ||
(type == ECORE_CON_REMOTE_NODELAY) ||
(type == ECORE_CON_REMOTE_UDP) ||
*/
void
+ecore_con_event_proxy_bind(Ecore_Con_Server *svr)
+{
+ Ecore_Con_Event_Proxy_Bind *e;
+ int ev = ECORE_CON_EVENT_PROXY_BIND;
+
+ e = ecore_con_event_proxy_bind_alloc();
+ EINA_SAFETY_ON_NULL_RETURN(e);
+
+ svr->event_count = eina_list_append(svr->event_count, e);
+ _ecore_con_server_timer_update(svr);
+ e->server = svr;
+ e->ip = svr->proxyip;
+ e->port = svr->proxyport;
+ ecore_event_add(ev, e,
+ _ecore_con_event_server_add_free, NULL);
+ _ecore_con_event_count++;
+}
+
+void
ecore_con_event_server_add(Ecore_Con_Server *svr)
{
/* we got our server! */
e = ecore_con_event_server_add_alloc();
EINA_SAFETY_ON_NULL_RETURN(e);
+ svr->connecting = EINA_FALSE;
+ svr->start_time = ecore_time_get();
svr->event_count = eina_list_append(svr->event_count, e);
_ecore_con_server_timer_update(svr);
e->server = svr;
eina_stringshare_del(svr->ip);
+ if (svr->ecs_buf) eina_binbuf_free(svr->ecs_buf);
+ if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
+
if (svr->fd_handler)
ecore_main_fd_handler_del(svr->fd_handler);
return;
}
-static void
+void
_ecore_con_server_kill(Ecore_Con_Server *svr)
{
if (!svr->delete_me)
goto error;
}
- svr->ip = eina_stringshare_add(net_info->ip);
+ if ((!svr->ecs) || (svr->ecs->lookup))
+ svr->ip = eina_stringshare_add(net_info->ip);
return;
goto error;
}
- svr->ip = eina_stringshare_add(net_info->ip);
+ if ((!svr->ecs) || (svr->ecs->lookup))
+ svr->ip = eina_stringshare_add(net_info->ip);
return;
if ((!svr->delete_me) && (!svr->handshaking) && svr->connecting)
{
- svr->connecting = EINA_FALSE;
- svr->start_time = ecore_time_get();
- ecore_con_event_server_add(svr);
+ if (svr->ecs)
+ {
+ if (ecore_con_socks_svr_init(svr))
+ return ECORE_CON_INPROGRESS;
+ }
+ else
+ ecore_con_event_server_add(svr);
}
if (svr->fd_handler && (!svr->buf))
static void
_ecore_con_cl_read(Ecore_Con_Server *svr)
{
- DBG("svr=%p", svr);
int num = 0;
Eina_Bool lost_server = EINA_TRUE;
unsigned char buf[READBUFSIZ];
+ DBG("svr=%p", svr);
+
/* only possible with non-ssl connections */
if (svr->connecting && (svr_try_connect_plain(svr) != ECORE_CON_CONNECTED))
return;
}
if ((!svr->delete_me) && (num > 0))
- ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
+ {
+ if (svr->ecs_state)
+ ecore_con_socks_read(svr, buf, num);
+ else
+ ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
+ }
if (lost_server)
_ecore_con_server_kill(svr);
want_read = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ);
want_write = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE);
- if (svr->handshaking && (want_read || want_write))
+ if ((!svr->ecs_state) && svr->handshaking && (want_read || want_write))
{
DBG("Continuing ssl handshake: preparing to %s...", want_read ? "read" : "write");
#ifdef ISCOMFITOR
}
else if (!svr->ssl_state)
+ ecore_con_event_server_add(svr);
+ return ECORE_CALLBACK_RENEW;
+ }
+ if (svr->ecs && svr->ecs_state && (svr->ecs_state < ECORE_CON_SOCKS_STATE_READ) && (!svr->ecs_buf))
+ {
+ if (svr->ecs_state < ECORE_CON_SOCKS_STATE_INIT)
{
- svr->connecting = EINA_FALSE;
- svr->start_time = ecore_time_get();
- ecore_con_event_server_add(svr);
+ INF("PROXY STATE++");
+ svr->ecs_state++;
}
+ if (ecore_con_socks_svr_init(svr)) return ECORE_CALLBACK_RENEW;
}
- else if (want_read)
+ if (want_read)
_ecore_con_cl_read(svr);
else if (want_write) /* only possible with non-ssl connections */
{
- if (svr->connecting && (!svr_try_connect_plain(svr)))
+ if (svr->connecting && (!svr_try_connect_plain(svr)) && (!svr->ecs_state))
return ECORE_CALLBACK_RENEW;
_ecore_con_server_flush(svr);
_ecore_con_server_flush(Ecore_Con_Server *svr)
{
int count, num;
+ size_t buf_len, buf_offset;
+ const void *buf;
#ifdef _WIN32
if (ecore_con_local_win32_server_flush(svr))
return;
#endif
- if ((!svr->buf) && svr->fd_handler)
+ if ((!svr->buf) && (!svr->ecs_buf) && svr->fd_handler)
{
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
return;
}
- num = eina_binbuf_length_get(svr->buf) - svr->write_buf_offset;
+ buf = svr->buf ? eina_binbuf_string_get(svr->buf) : eina_binbuf_string_get(svr->ecs_buf);
+ buf_len = svr->buf ? eina_binbuf_length_get(svr->buf) : eina_binbuf_length_get(svr->ecs_buf);
+ buf_offset = svr->buf ? svr->write_buf_offset : svr->ecs_buf_offset;
+ num = buf_len - buf_offset;
/* check whether we need to write anything at all.
* we must not write zero bytes with SSL_write() since it
}
if (!(svr->type & ECORE_CON_SSL))
- count = write(svr->fd, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num);
+ count = write(svr->fd, buf + buf_offset, num);
else
- count = ecore_con_ssl_server_write(svr, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num);
+ count = ecore_con_ssl_server_write(svr, buf + buf_offset, num);
if (count < 0)
{
return;
}
- if (count) ecore_con_event_server_write(svr, count);
- svr->write_buf_offset += count;
- if (svr->write_buf_offset >= eina_binbuf_length_get(svr->buf))
+ if (count && (!svr->ecs_state)) ecore_con_event_server_write(svr, count);
+ if (svr->ecs_buf)
+ buf_offset = svr->ecs_buf_offset += count;
+ else
+ buf_offset = svr->write_buf_offset += count;
+ if (buf_offset >= buf_len)
{
- svr->write_buf_offset = 0;
- eina_binbuf_free(svr->buf);
- svr->buf = NULL;
+ if (svr->ecs_buf)
+ {
+ svr->ecs_buf_offset = 0;
+ eina_binbuf_free(svr->ecs_buf);
+ svr->ecs_buf = NULL;
+ INF("PROXY STATE++");
+ svr->ecs_state++;
+ }
+ else
+ {
+ svr->write_buf_offset = 0;
+ eina_binbuf_free(svr->buf);
+ svr->buf = NULL;
+ }
+
if (svr->fd_handler)
ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
}
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
+GENERIC_ALLOC_FREE(Ecore_Con_Event_Proxy_Bind, ecore_con_event_proxy_bind);
static Ecore_Con_Mempool *mempool_array[] = {
&ecore_con_event_client_add_mp,
&ecore_con_event_server_add_mp,
&ecore_con_event_server_del_mp,
&ecore_con_event_server_write_mp,
- &ecore_con_event_server_data_mp
+ &ecore_con_event_server_data_mp,
+ &ecore_con_event_proxy_bind_mp
};
void
memcpy(&cares->hints, hints, sizeof(struct addrinfo));
}
- if (inet_pton(AF_INET, svr->name, &cares->addr.v4) == 1)
+ if (inet_pton(AF_INET, svr->ecs : svr->ecs->ip : svr->name, &cares->addr.v4) == 1)
{
cares->byaddr = EINA_TRUE;
cares->isv6 = EINA_FALSE;
cares);
}
#ifdef HAVE_IPV6
- else if (inet_pton(AF_INET6, svr->name, &cares->addr.v6) == 1)
+ else if (inet_pton(AF_INET6, svr->ecs : svr->ecs->ip : svr->name, &cares->addr.v6) == 1)
{
cares->byaddr = EINA_TRUE;
cares->isv6 = EINA_TRUE;
else
{
cares->byaddr = EINA_FALSE;
- ares_gethostbyname(info_channel, svr->name, ai_family,
+ ares_gethostbyname(info_channel, svr->ecs : svr->ecs->ip : svr->name, ai_family,
(ares_host_callback)_ecore_con_info_ares_host_cb,
cares);
}
goto on_mem_error;
addri->sin_family = AF_INET;
- addri->sin_port = htons(arg->svr->port);
+ addri->sin_port = htons(arg->svr->ecs : svr->ecs->port : svr->port);
memcpy(&addri->sin_addr.s_addr,
hostent->h_addr_list[0], sizeof(struct in_addr));
goto on_mem_error;
addri6->sin6_family = AF_INET6;
- addri6->sin6_port = htons(arg->svr->port);
+ addri6->sin6_port = htons(arg->svr->ecs : svr->ecs->port : svr->port);
addri6->sin6_flowinfo = 0;
addri6->sin6_scope_id = 0;
goto on_mem_error;
addri6->sin6_family = AF_INET6;
- addri6->sin6_port = htons(arg->svr->port);
+ addri6->sin6_port = htons(arg->svr->ecs : svr->ecs->port : svr->port);
addri6->sin6_flowinfo = 0;
addri6->sin6_scope_id = 0;
goto on_mem_error;
addri->sin_family = AF_INET;
- addri->sin_port = htons(arg->svr->port);
+ addri->sin_port = htons(arg->svr->ecs : svr->ecs->port : svr->port);
memcpy(&addri->sin_addr.s_addr,
&arg->addr.v4, sizeof(struct in_addr));
int canonname_len = 0;
int err;
- eina_convert_itoa(svr->port, service);
+ eina_convert_itoa(svr->ecs ? svr->ecs->port : svr->port, service);
/* CHILD */
- if (!getaddrinfo(svr->name, service, hints, &result) && result)
+ if (!getaddrinfo(svr->ecs ? svr->ecs->ip : svr->name, service, hints, &result) && result)
{
if (result->ai_canonname)
canonname_len = strlen(result->ai_canonname) + 1;
typedef struct _Ecore_Con_Lookup Ecore_Con_Lookup;
typedef struct _Ecore_Con_Info Ecore_Con_Info;
-
+typedef struct Ecore_Con_Socks_v4 Ecore_Con_Socks_v4;
+typedef struct Ecore_Con_Socks_v5 Ecore_Con_Socks_v5;
typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
typedef enum _Ecore_Con_State
ECORE_CON_SSL_STATE_INIT
} Ecore_Con_Ssl_State;
+typedef enum Ecore_Con_Socks_State
+{
+ ECORE_CON_SOCKS_STATE_DONE = 0,
+ ECORE_CON_SOCKS_STATE_RESOLVED,
+ ECORE_CON_SOCKS_STATE_INIT,
+ ECORE_CON_SOCKS_STATE_READ
+} Ecore_Con_Socks_State;
+
struct _Ecore_Con_Client
{
ECORE_MAGIC;
Eina_List *event_count;
int client_limit;
pid_t ppid;
+ /* socks */
+ Ecore_Con_Socks *ecs;
+ Ecore_Con_Socks_State ecs_state;
+ int ecs_addrlen;
+ unsigned char ecs_addr[16];
+ unsigned int ecs_buf_offset;
+ Eina_Binbuf *ecs_buf;
+ Eina_Binbuf *ecs_recvbuf;
+ const char *proxyip;
+ int proxyport;
+ /* endsocks */
#if USE_GNUTLS
gnutls_session_t session;
gnutls_anon_client_credentials_t anoncred_c;
const void *data;
};
+#define ECORE_CON_SOCKS_CAST_ELSE(X) \
+ Ecore_Con_Socks_v4 *v4 = NULL; \
+ Ecore_Con_Socks_v5 *v5 = NULL; \
+ if ((X) && ((X)->version == 4)) \
+ v4 = (Ecore_Con_Socks_v4*)(X); \
+ else if ((X) && ((X)->version == 5)) \
+ v5 = (Ecore_Con_Socks_v5*)(X); \
+ else
+
+struct Ecore_Con_Socks
+{
+ unsigned char version;
+
+ const char *ip;
+ int port;
+ const char *username;
+ Eina_Bool lookup : 1;
+ Eina_Bool bind : 1;
+};
+
+struct Ecore_Con_Socks_v4
+{
+ unsigned char version;
+
+ const char *ip;
+ int port;
+ const char *username;
+ Eina_Bool lookup : 1;
+ Eina_Bool bind : 1;
+};
+
+struct Ecore_Con_Socks_v5
+{
+ unsigned char version;
+
+ const char *ip;
+ int port;
+ const char *username;
+ Eina_Bool lookup : 1;
+ Eina_Bool bind : 1;
+};
+
+extern Ecore_Con_Socks *_ecore_con_proxy_once;
+extern Ecore_Con_Socks *_ecore_con_proxy_global;
+void ecore_con_socks_init(void);
+void ecore_con_socks_shutdown(void);
+Eina_Bool ecore_con_socks_svr_init(Ecore_Con_Server *svr);
+void ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num);
+void ecore_con_socks_dns_cb(const char *canonname, const char *ip, struct sockaddr *addr, int addrlen, Ecore_Con_Server *svr);
/* from ecore_con.c */
void ecore_con_server_infos_del(Ecore_Con_Server *svr, void *info);
+void ecore_con_event_proxy_bind(Ecore_Con_Server *svr);
void ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate);
void ecore_con_event_server_del(Ecore_Con_Server *svr);
void ecore_con_event_server_error(Ecore_Con_Server *svr, const char *error);
void ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate);
void ecore_con_event_client_del(Ecore_Con_Client *cl);
void ecore_con_event_client_error(Ecore_Con_Client *cl, const char *error);
-
+void _ecore_con_server_kill(Ecore_Con_Server *svr);
/* from ecore_local_win32.c */
#ifdef _WIN32
Eina_Bool ecore_con_local_listen(Ecore_Con_Server *svr);
GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
+GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Proxy_Bind, ecore_con_event_proxy_bind);
void ecore_con_mempool_init(void);
void ecore_con_mempool_shutdown(void);