forked from enlightenment/efl
optimize read mechanics for remote servers using ioctl to determine number of bytes available for reading.
in general, this should provide an improvement which scales with the amount of data being transferred: * small transfers will incur a small amount of overhead from potentially unneeded memory as I try to account for a bug in FIONREAD which returns a number that is smaller than the actual number of bytes available for read on a socket * large transfers will no longer require any copies of the data on systems which do not provide the FIONREAD ioctl(), old functionality will be used this should work on windows, though I (obviously) can't test it myself thus ends the longest commit message I have ever written SVN revision: 66063
This commit is contained in:
parent
e8a3c54734
commit
0b109fb5c2
|
@ -390,3 +390,7 @@
|
|||
* Allow SSL certificates to be loaded for STARTTLS
|
||||
* Added functions to set/get the hostname used for SSL certificate verification
|
||||
* ecore_con_ssl_server_cafile_add() now accepts directories
|
||||
|
||||
2011-12-09 Mike Blumenkrantz
|
||||
|
||||
* Created optimized reading mechanism for remote server connections
|
||||
|
|
|
@ -1415,6 +1415,7 @@ AC_ARG_ENABLE([ipv6],
|
|||
|
||||
if test "x${have_ecore_con}" = "xyes" ; then
|
||||
|
||||
AC_CHECK_HEADERS([sys/ioctl.h winsock2.h])
|
||||
# Verify IPV6 availability in headers
|
||||
if test "x${want_ipv6}" != "xno" ; then
|
||||
AC_CHECK_TYPES([struct ipv6_mreq],
|
||||
|
|
|
@ -38,6 +38,14 @@
|
|||
# include <Evil.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "Ecore.h"
|
||||
#include "ecore_private.h"
|
||||
#include "Ecore_Con.h"
|
||||
|
@ -1049,7 +1057,11 @@ ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num,
|
|||
Ecore_Con_Event_Server_Data *e;
|
||||
|
||||
e = ecore_con_event_server_data_alloc();
|
||||
EINA_SAFETY_ON_NULL_RETURN(e);
|
||||
if (!e)
|
||||
{
|
||||
if (!duplicate) free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
svr->event_count = eina_list_append(svr->event_count, e);
|
||||
_ecore_con_server_timer_update(svr);
|
||||
|
@ -1999,9 +2011,14 @@ _ecore_con_svr_tcp_handler(void *data,
|
|||
static void
|
||||
_ecore_con_cl_read(Ecore_Con_Server *svr)
|
||||
{
|
||||
int num = 0;
|
||||
Eina_Bool lost_server = EINA_TRUE;
|
||||
int num2 = 0, num = 0;
|
||||
#ifdef FIONREAD
|
||||
double lr;
|
||||
unsigned char *buf = NULL;
|
||||
#else
|
||||
unsigned char buf[READBUFSIZ];
|
||||
#endif
|
||||
Eina_Bool lost_server = EINA_TRUE;
|
||||
|
||||
DBG("svr=%p", svr);
|
||||
|
||||
|
@ -2016,23 +2033,42 @@ _ecore_con_cl_read(Ecore_Con_Server *svr)
|
|||
lost_server = EINA_FALSE;
|
||||
_ecore_con_server_timer_update(svr);
|
||||
}
|
||||
|
||||
#ifdef FIONREAD
|
||||
# ifdef _WIN32
|
||||
if (ioctlsocket(svr->fd, FIONREAD, &num)) goto error;
|
||||
# else
|
||||
errno = 0;
|
||||
if (ioctl(svr->fd, FIONREAD, &num)) goto error;
|
||||
# endif
|
||||
if (!num) return; /* FIXME: this shouldn't happen */
|
||||
lr = ecore_time_get();
|
||||
if ((num < 100) && (lr - svr->last_read < 0.01)) num2 = READBUFSIZ / 8;
|
||||
else if (num > READBUFSIZ) num2 = READBUFSIZ;
|
||||
if (num2)
|
||||
{
|
||||
DBG("%d bytes available for read from ioctl(), trying size (%d) to avoid congestion", num, num2);
|
||||
num = num2;
|
||||
}
|
||||
else
|
||||
DBG("%d bytes available for read", num);
|
||||
svr->last_read = lr;
|
||||
buf = malloc(num);
|
||||
if (!buf) goto error;
|
||||
#else
|
||||
num = sizeof(buf);
|
||||
(void)num2;
|
||||
#endif
|
||||
if (svr->ecs_state || !(svr->type & ECORE_CON_SSL))
|
||||
{
|
||||
errno = 0;
|
||||
num = read(svr->fd, buf, sizeof(buf));
|
||||
num = read(svr->fd, buf, num);
|
||||
/* 0 is not a valid return value for a tcp socket */
|
||||
if ((num > 0) || ((num < 0) && (errno == EAGAIN)))
|
||||
lost_server = EINA_FALSE;
|
||||
else if (num < 0)
|
||||
ecore_con_event_server_error(svr, strerror(errno));
|
||||
if ((num < 0) || (errno && (errno != EAGAIN))) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = ecore_con_ssl_server_read(svr, buf, sizeof(buf));
|
||||
num = ecore_con_ssl_server_read(svr, buf, num);
|
||||
/* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
|
||||
if (num >= 0)
|
||||
lost_server = EINA_FALSE;
|
||||
if (num < 0) goto error;
|
||||
}
|
||||
|
||||
if ((!svr->delete_me) && (num > 0))
|
||||
|
@ -2040,11 +2076,25 @@ _ecore_con_cl_read(Ecore_Con_Server *svr)
|
|||
if (svr->ecs_state)
|
||||
ecore_con_socks_read(svr, buf, num);
|
||||
else
|
||||
ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
|
||||
ecore_con_event_server_data(svr, buf, num,
|
||||
#ifdef FIONREAD
|
||||
EINA_FALSE
|
||||
#else
|
||||
EINA_TRUE
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
if (lost_server)
|
||||
_ecore_con_server_kill(svr);
|
||||
return;
|
||||
error:
|
||||
#ifndef _WIN32
|
||||
/* FIXME: strerror on windows */
|
||||
ecore_con_event_server_error(svr, strerror(errno));
|
||||
#endif
|
||||
#ifdef FIONREAD
|
||||
free(buf);
|
||||
#endif
|
||||
_ecore_con_server_kill(svr);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
|
|
|
@ -150,6 +150,7 @@ struct _Ecore_Con_Server
|
|||
const char *proxyip;
|
||||
int proxyport;
|
||||
/* endsocks */
|
||||
/* SSL */
|
||||
const char *verify_name;
|
||||
#if USE_GNUTLS
|
||||
gnutls_session_t session;
|
||||
|
@ -165,7 +166,9 @@ struct _Ecore_Con_Server
|
|||
SSL *ssl;
|
||||
int ssl_err;
|
||||
#endif
|
||||
/* ENDSSL */
|
||||
double start_time;
|
||||
double last_read;
|
||||
Ecore_Timer *until_deletion;
|
||||
double disconnect_time;
|
||||
double client_disconnect_time;
|
||||
|
|
|
@ -103,11 +103,25 @@ ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num)
|
|||
DBG("SOCKS: %d bytes", num);
|
||||
if (num < 8)
|
||||
{
|
||||
#ifdef FIONREAD
|
||||
if (!svr->ecs_recvbuf)
|
||||
svr->ecs_recvbuf = eina_binbuf_manage_new_length(buf, num);
|
||||
else
|
||||
eina_binbuf_append_length(svr->ecs_recvbuf, buf, num);
|
||||
if (!svr->ecs_recvbuf) goto error;
|
||||
#else
|
||||
if (!svr->ecs_recvbuf) svr->ecs_recvbuf = eina_binbuf_new();
|
||||
if (!svr->ecs_recvbuf) goto error;
|
||||
eina_binbuf_append_length(svr->ecs_recvbuf, buf, num);
|
||||
#endif
|
||||
/* the slowest connection on earth */
|
||||
if (eina_binbuf_length_get(svr->ecs_recvbuf) != 8) return;
|
||||
if (eina_binbuf_length_get(svr->ecs_recvbuf) != 8)
|
||||
{
|
||||
#ifdef FIONREAD
|
||||
free(buf);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
data = eina_binbuf_string_get(svr->ecs_recvbuf);
|
||||
}
|
||||
else if (num > 8) goto error;
|
||||
|
@ -149,6 +163,9 @@ ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num)
|
|||
svr->ecs_state = ECORE_CON_SOCKS_STATE_DONE;
|
||||
INF("PROXY CONNECTED");
|
||||
if (svr->ecs_recvbuf) eina_binbuf_free(svr->ecs_recvbuf);
|
||||
#ifdef FIONREAD
|
||||
else free(buf);
|
||||
#endif
|
||||
svr->ecs_recvbuf = NULL;
|
||||
svr->ecs_buf_offset = svr->ecs_addrlen = 0;
|
||||
memset(svr->ecs_addr, 0, sizeof(svr->ecs_addr));
|
||||
|
@ -159,6 +176,9 @@ ecore_con_socks_read(Ecore_Con_Server *svr, unsigned char *buf, int num)
|
|||
}
|
||||
return;
|
||||
error:
|
||||
#ifdef FIONREAD
|
||||
free(buf);
|
||||
#endif
|
||||
_ecore_con_server_kill(svr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue