Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

...
 
Commits (1)
  • Deucе's avatar
    Use new PREFER_POLL define to control poll() usage · 3de05e2d
    Deucе authored
    Rather than depending on _WIN32 which is silly, make it clear what
    exactly is being done and why.
    
    Note that the spy socket stuff and some external stuff on *nix have
    had the select() implementation removed.  To support using select()
    on !Win32 will require de-refactoring that's not really worth doing.
    Instead, just use #error and reference the commit where the old
    code can be found.
    3de05e2d
......@@ -214,6 +214,10 @@ ifndef os
endif
os := $(shell echo $(os) | tr '[A-Z]' '[a-z]' | tr ' ' '_')
ifneq ($(os),Win32)
CFLAGS += -DPREFER_POLL
endif
machine := $(shell if uname -m | egrep -v "(i[3456789]*|x)86" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; fi)
machine := $(shell if uname -m | egrep "64" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; else echo $(machine) ; fi)
ifeq ($(os),darwin)
......
......@@ -3695,19 +3695,19 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JSObject* robj;
JSObject* rarray;
BOOL poll_for_write=FALSE;
#ifdef _WIN32
fd_set socket_set[3];
fd_set* sets[3] = {NULL, NULL, NULL};
SOCKET maxsock=0;
struct timeval tv = {0, 0};
SOCKET sock;
#else
#ifdef PREFER_POLL
struct pollfd *fds;
int poll_timeout = 0;
nfds_t nfds;
short events;
int scount;
int k;
#else
fd_set socket_set[3];
fd_set* sets[3] = {NULL, NULL, NULL};
SOCKET maxsock=0;
struct timeval tv = {0, 0};
SOCKET sock;
#endif
uintN argn;
jsuint i;
......@@ -3726,12 +3726,12 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
else if(JSVAL_IS_OBJECT(argv[argn]))
inarray[inarray_cnt++] = JSVAL_TO_OBJECT(argv[argn]);
#ifdef _WIN32
#ifdef PREFER_POLL
else if(JSVAL_IS_NUMBER(argv[argn]))
js_timeval(cx,argv[argn],&tv);
poll_timeout = js_polltimeout(cx, argv[argn]);
#else
else if(JSVAL_IS_NUMBER(argv[argn]))
poll_timeout = js_polltimeout(cx, argv[argn]);
js_timeval(cx,argv[argn],&tv);
#endif
}
......@@ -3753,42 +3753,7 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
/* Return array */
if((robj = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
#ifdef _WIN32
FD_ZERO(&socket_set[0]);
if(poll_for_write)
sets[1]=&socket_set[0];
else
sets[0]=&socket_set[0];
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[0]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
if(js_socket_isset(cx,val,&socket_set[0])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, robj, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#else
#ifdef PREFER_POLL
// First, count the number of sockets...
nfds = 0;
for (i = 0; i < limit[0]; i++) {
......@@ -3837,66 +3802,51 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
free(fds);
#endif
JS_RESUMEREQUEST(cx, rc);
#else
FD_ZERO(&socket_set[0]);
if(poll_for_write)
sets[1]=&socket_set[0];
else
sets[0]=&socket_set[0];
return(JS_TRUE);
}
else {
/* Return object */
if((robj = JS_NewObject(cx, NULL, NULL, NULL))==NULL)
return(JS_FALSE);
#ifdef _WIN32
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
FD_ZERO(&socket_set[j]);
sets[j] = &socket_set[j];
for (i = 0; i < limit[j]; i++) {
if(!JS_GetElement(cx, inarray[j], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[j]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[0]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
len = 0;
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
if(js_socket_isset(cx,val,&socket_set[0])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
val = OBJECT_TO_JSVAL(rarray);
if (!JS_SetProperty(cx, robj, props[j], &val))
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
for(i=0;i<limit[j];i++) {
JS_RESUMEREQUEST(cx, rc);
if(!JS_GetElement(cx, inarray[j], i, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
if(!JS_SetElement(cx, robj, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
if(js_socket_isset(cx,val,&socket_set[j])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, rarray, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#else
#endif
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
else {
/* Return object */
if((robj = JS_NewObject(cx, NULL, NULL, NULL))==NULL)
return(JS_FALSE);
#ifdef PREFER_POLL
/*
* So, we need to collapse all the FDs into a list with flags set...
* readfd corresponds to POLLIN
......@@ -4011,6 +3961,56 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
free(fds);
#else
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
FD_ZERO(&socket_set[j]);
sets[j] = &socket_set[j];
for (i = 0; i < limit[j]; i++) {
if(!JS_GetElement(cx, inarray[j], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[j]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
len = 0;
JS_RESUMEREQUEST(cx, rc);
if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
val = OBJECT_TO_JSVAL(rarray);
if (!JS_SetProperty(cx, robj, props[j], &val))
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
for(i=0;i<limit[j];i++) {
JS_RESUMEREQUEST(cx, rc);
if(!JS_GetElement(cx, inarray[j], i, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
if(js_socket_isset(cx,val,&socket_set[j])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, rarray, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#endif
JS_RESUMEREQUEST(cx, rc);
......
......@@ -472,14 +472,15 @@ SOCKET DLLCALL js_socket(JSContext *cx, jsval val)
return(sock);
}
#ifdef _WIN32
SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
#ifdef PREFER_POLL
size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -488,33 +489,33 @@ SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
FD_SET(p->set->socks[i].sock, fds);
if(p->set->socks[i].sock > sock)
sock = p->set->socks[i].sock;
ret++;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET)
FD_SET(p->sock, fds);
ret = 1;
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
sock = intval;
FD_SET(sock, fds);
if (intval != INVALID_SOCKET)
ret = 1;
}
}
return sock;
return ret;
}
BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int intval;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -523,51 +524,38 @@ BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
if(FD_ISSET(p->set->socks[i].sock, fds))
return TRUE;
fds[ret].events = events;
fds[ret++].fd = p->set->socks[i].sock;
}
}
else {
if (p->sock == INVALID_SOCKET)
return TRUE;
else {
if(FD_ISSET(p->sock, fds))
return TRUE;
sock = p->sock;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
if(FD_ISSET(intval, fds))
return TRUE;
}
}
return FALSE;
}
void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv)
{
jsdouble jsd;
if(JSVAL_IS_INT(val))
tv->tv_sec = JSVAL_TO_INT(val);
else if(JSVAL_IS_DOUBLE(val)) {
if(JS_ValueToNumber(cx,val,&jsd)) {
tv->tv_sec = (int)jsd;
tv->tv_usec = (int)(jsd*1000000.0)%1000000;
sock = intval;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
}
}
return ret;
}
#else
size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -576,33 +564,33 @@ size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
ret++;
FD_SET(p->set->socks[i].sock, fds);
if(p->set->socks[i].sock > sock)
sock = p->set->socks[i].sock;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET)
ret = 1;
FD_SET(p->sock, fds);
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
if (intval != INVALID_SOCKET)
ret = 1;
sock = intval;
FD_SET(sock, fds);
}
}
return ret;
return sock;
}
size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events)
BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
int intval;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -611,29 +599,41 @@ size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
fds[ret].events = events;
fds[ret++].fd = p->set->socks[i].sock;
if(FD_ISSET(p->set->socks[i].sock, fds))
return TRUE;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
if (p->sock == INVALID_SOCKET)
return TRUE;
else {
if(FD_ISSET(p->sock, fds))
return TRUE;
}
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
sock = intval;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
if(FD_ISSET(intval, fds))
return TRUE;
}
}
return FALSE;
}
void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv)
{
jsdouble jsd;
if(JSVAL_IS_INT(val))
tv->tv_sec = JSVAL_TO_INT(val);
else if(JSVAL_IS_DOUBLE(val)) {
if(JS_ValueToNumber(cx,val,&jsd)) {
tv->tv_sec = (int)jsd;
tv->tv_usec = (int)(jsd*1000000.0)%1000000;
}
}
return ret;
}
#endif
......@@ -1730,18 +1730,18 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
uintN argn;
int result;
jsrefcount rc;
#ifdef _WIN32
#ifdef PREFER_POLL
int timeout = 0;
struct pollfd *fds;
nfds_t nfds;
jsval objval = OBJECT_TO_JSVAL(obj);
#else
size_t i;
SOCKET high=0;
fd_set socket_set;
fd_set* rd_set=NULL;
fd_set* wr_set=NULL;
struct timeval tv = {0, 0};
#else
int timeout = 0;
struct pollfd *fds;
nfds_t nfds;
jsval objval = OBJECT_TO_JSVAL(obj);
#endif
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
......@@ -1760,16 +1760,33 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
if(JSVAL_IS_BOOLEAN(argv[argn]))
poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
else if(JSVAL_IS_NUMBER(argv[argn])) {
#ifdef _WIN32
js_timeval(cx,argv[argn],&tv);
#else
#ifdef PREFER_POLL
timeout = js_polltimeout(cx, argv[argn]);
#else
js_timeval(cx,argv[argn],&tv);
#endif
}
}
rc=JS_SUSPENDREQUEST(cx);
#ifdef _WIN32
#ifdef PREFER_POLL
if (p->peeked && !poll_for_write) {
result = 1;
}
else {
nfds = js_socket_numsocks(cx, objval);
fds = calloc(nfds, sizeof(*fds));
if (fds == NULL) {
JS_RESUMEREQUEST(cx, rc);
JS_ReportError(cx, "Error allocating %d elements of %lu bytes at %s:%d"
, nfds, sizeof(*fds), getfname(__FILE__), __LINE__);
return JS_FALSE;
}
nfds = js_socket_add(cx, objval, fds, poll_for_write ? POLLOUT : POLLIN);
result = poll(fds, nfds, timeout);
free(fds);
}
#else
FD_ZERO(&socket_set);
if(p->set) {
for(i=0; i<p->set->sock_count; i++) {
......@@ -1791,23 +1808,6 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
result = 1;
else
result = select(high+1,rd_set,wr_set,NULL,&tv);
#else
if (p->peeked && !poll_for_write) {
result = 1;
}
else {
nfds = js_socket_numsocks(cx, objval);
fds = calloc(nfds, sizeof(*fds));
if (fds == NULL) {
JS_RESUMEREQUEST(cx, rc);
JS_ReportError(cx, "Error allocating %d elements of %lu bytes at %s:%d"
, nfds, sizeof(*fds), getfname(__FILE__), __LINE__);
return JS_FALSE;
}
nfds = js_socket_add(cx, objval, fds, poll_for_write ? POLLOUT : POLLIN);
result = poll(fds, nfds, timeout);
free(fds);
}
#endif
p->last_error=ERROR_VALUE;
......
......@@ -1870,9 +1870,14 @@ void input_thread(void *arg)
ulong total_pkts=0;
sbbs_t* sbbs = (sbbs_t*) arg;
SOCKET sock;
#ifndef _WIN32
#ifdef PREFER_POLL
struct pollfd fds[2];
int nfds;
#else
fd_set socket_set;
struct timeval tv;
SOCKET high_socket;
SOCKET sock;
#endif
SetThreadName("sbbs/termInput");
......@@ -1890,7 +1895,7 @@ void input_thread(void *arg)
if(pthread_mutex_lock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_LOCK,"input_thread_mutex",0);
#ifdef _WIN32
#ifdef _WIN32 // No spy sockets
if (!socket_readable(sbbs->client_socket, 1000)) {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
......@@ -1898,6 +1903,7 @@ void input_thread(void *arg)
continue; /* to allow other threads to lock the input_thread_mutex */
}
#else
#ifdef PREFER_POLL
fds[0].fd = sbbs->client_socket;
fds[0].events = POLLIN;
fds[0].revents = 0;
......@@ -1915,6 +1921,9 @@ void input_thread(void *arg)
YIELD(); /* This kludge is necessary on some Linux distros */
continue; /* to allow other threads to lock the input_thread_mutex */
}
#else
#error Spy sockets without poll() was removed in commit 3971ef4dcc3db19f400a648b6110718e56a64cf3
#endif
#endif
if(sbbs->client_socket==INVALID_SOCKET) {
......@@ -1934,12 +1943,13 @@ void input_thread(void *arg)
* ------------
*/
#ifdef _WIN32
#ifdef _WIN32 // No spy sockets
sock=sbbs->client_socket;
#else
if (fds[0].revents | POLLIN)
#ifdef PREFER_POLL
if (fds[0].revents & POLLIN)
sock = sbbs->client_socket;
else if(uspy_socket[sbbs->cfg.node_num - 1] != INVALID_SOCKET && fds[1].revents | POLLIN) {
else if(uspy_socket[sbbs->cfg.node_num - 1] != INVALID_SOCKET && fds[1].revents & POLLIN) {
if(socket_recvdone(uspy_socket[sbbs->cfg.node_num-1], 0)) {
close_socket(uspy_socket[sbbs->cfg.node_num-1]);
lprintf(LOG_NOTICE,"Closing local spy socket: %d",uspy_socket[sbbs->cfg.node_num-1]);
......@@ -1955,6 +1965,9 @@ void input_thread(void *arg)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
continue;
}
#else
#error Spy sockets without poll() was removed in commit 3971ef4dcc3db19f400a648b6110718e56a64cf3
#endif
#endif
rd=RingBufFree(&sbbs->inbuf);
......
......@@ -1354,13 +1354,13 @@ extern "C" {
DLLEXPORT SOCKET DLLCALL js_socket(JSContext *cx, jsval val);
DLLEXPORT int js_polltimeout(JSContext* cx, jsval val);
#ifdef _WIN32
#ifdef PREFER_POLL
DLLEXPORT size_t js_socket_numsocks(JSContext *cx, jsval val);
DLLEXPORT size_t js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events);
#else
DLLEXPORT void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv);
DLLEXPORT SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds);
DLLEXPORT BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds);
#else
DLLEXPORT size_t js_socket_numsocks(JSContext *cx, jsval val);
DLLEXPORT size_t js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events);
#endif
/* js_queue.c */
......
......@@ -1722,7 +1722,7 @@ void service_udp_sock_cb(SOCKET sock, void *cbdata)
#endif
}
#ifndef _WIN32
#ifdef PREFER_POLL
/*
* Sets up the fds for poll, and returns the total sockets
*/
......@@ -1787,14 +1787,14 @@ void DLLCALL services_thread(void* arg)
char *ssl_estr;
int level;
BOOL need_cert = FALSE;
#ifdef _WIN32
fd_set socket_set;
SOCKET high_socket;
struct timeval tv;
#else
#ifdef PREFER_POLL
struct pollfd *fds = NULL;
nfds_t nfds;
nfds_t nfdsi;
#else
fd_set socket_set;
SOCKET high_socket;
struct timeval tv;
#endif
startup=(services_startup_t*)arg;
......@@ -2001,7 +2001,7 @@ void DLLCALL services_thread(void* arg)
lprintf(LOG_INFO,"0000 Services thread started (%lu service sockets bound)", total_sockets);
#ifndef _WIN32
#ifdef PREFER_POLL
nfds = setup_poll(&fds);
if (nfds == 0) {
lprintf(LOG_CRIT, "!ERROR setting up poll() data");
......@@ -2034,92 +2034,92 @@ void DLLCALL services_thread(void* arg)
}
}
#ifdef _WIN32
/* Setup select() parms */
FD_ZERO(&socket_set);
high_socket=0;
#ifdef PREFER_POLL
/* Clear poll FDs where necessary (ie: when !SERVICE_OPT_FULL_ACCEPT) */
nfdsi = 0;
for(i=0;i<(int)services;i++) {
if(service[i].options&SERVICE_OPT_STATIC)
continue;
if(service[i].set==NULL)
continue;
if(!(service[i].options&SERVICE_OPT_FULL_ACCEPT)
&& service[i].max_clients && protected_uint32_value(service[i].clients) >= service[i].max_clients)
continue;
for(j=0; j<service[i].set->sock_count; j++) {
FD_SET(service[i].set->socks[j].sock,&socket_set);
if(service[i].set->socks[j].sock>high_socket)
high_socket=service[i].set->socks[j].sock;
if(!(service[i].options&SERVICE_OPT_FULL_ACCEPT)) {
if (service[i].max_clients && protected_uint32_value(service[i].clients) >= service[i].max_clients) {
for(j=0; j<service[i].set->sock_count; j++)
fds[nfdsi + j].fd = -1;
}
else {
for(j=0; j<service[i].set->sock_count; j++)
fds[nfdsi + j].fd = service[i].set->socks[j].sock;
}
}
nfdsi += service[i].set->sock_count;
}
if(high_socket==0) /* No dynamic services? */
continue;
tv.tv_sec=startup->sem_chk_freq;
tv.tv_usec=0;
if((result=select(high_socket+1,&socket_set,NULL,NULL,&tv))<1) {
if ((result = poll(fds, nfds, startup->sem_chk_freq * 1000)) < 1) {
if(result==0)
continue;
if(ERROR_VALUE==EINTR)
lprintf(LOG_DEBUG,"0000 Services listening interrupted");
else if(ERROR_VALUE == ENOTSOCK)
lprintf(LOG_NOTICE,"0000 Services sockets closed");
else
lprintf(LOG_WARNING,"0000 !ERROR %d selecting sockets: %s"
lprintf(LOG_WARNING,"0000 !ERROR %d polling sockets: %s"
, ERROR_VALUE, socket_strerror(socket_errno,error,sizeof(error)));
continue;
}
/* Determine who services this socket */
nfdsi = 0;
for(i=0;i<(int)services;i++) {
if(service[i].options&SERVICE_OPT_STATIC)
continue;
if(service[i].set==NULL)
continue;
for(j=0; j<service[i].set->sock_count; j++) {
if(!FD_ISSET(service[i].set->socks[j].sock,&socket_set))
if ((fds[nfdsi + j].revents & POLLIN) == 0)
continue;
#else
/* Clear poll FDs where necessary (ie: when !SERVICE_OPT_FULL_ACCEPT) */
nfdsi = 0;
/* Setup select() parms */
FD_ZERO(&socket_set);
high_socket=0;
for(i=0;i<(int)services;i++) {
if(service[i].options&SERVICE_OPT_STATIC)
continue;
if(service[i].set==NULL)
continue;
if(!(service[i].options&SERVICE_OPT_FULL_ACCEPT)) {
if (service[i].max_clients && protected_uint32_value(service[i].clients) >= service[i].max_clients) {
for(j=0; j<service[i].set->sock_count; j++)
fds[nfdsi + j].fd = -1;
}
else {
for(j=0; j<service[i].set->sock_count; j++)
fds[nfdsi + j].fd = service[i].set->socks[j].sock;
}
if(!(service[i].options&SERVICE_OPT_FULL_ACCEPT)
&& service[i].max_clients && protected_uint32_value(service[i].clients) >= service[i].max_clients)
continue;
for(j=0; j<service[i].set->sock_count; j++) {
FD_SET(service[i].set->socks[j].sock,&socket_set);
if(service[i].set->socks[j].sock>high_socket)
high_socket=service[i].set->socks[j].sock;
}
nfdsi += service[i].set->sock_count;
}
if ((result = poll(fds, nfds, startup->sem_chk_freq * 1000)) < 1) {
if(high_socket==0) /* No dynamic services? */
continue;
tv.tv_sec=startup->sem_chk_freq;
tv.tv_usec=0;
if((result=select(high_socket+1,&socket_set,NULL,NULL,&tv))<1) {
if(result==0)
continue;
if(ERROR_VALUE==EINTR)
lprintf(LOG_DEBUG,"0000 Services listening interrupted");
else if(ERROR_VALUE == ENOTSOCK)
lprintf(LOG_NOTICE,"0000 Services sockets closed");
else
lprintf(LOG_WARNING,"0000 !ERROR %d polling sockets: %s"
lprintf(LOG_WARNING,"0000 !ERROR %d selecting sockets: %s"
, ERROR_VALUE, socket_strerror(socket_errno,error,sizeof(error)));
continue;
}
nfdsi = 0;
/* Determine who services this socket */
for(i=0;i<(int)services;i++) {
if(service[i].options&SERVICE_OPT_STATIC)
continue;
if(service[i].set==NULL)
continue;
for(j=0; j<service[i].set->sock_count; j++) {
if ((fds[nfdsi + j].revents & POLLIN) == 0)
if(!FD_ISSET(service[i].set->socks[j].sock,&socket_set))
continue;
#endif
client_addr_len = sizeof(client_addr);
......@@ -2296,12 +2296,12 @@ void DLLCALL services_thread(void* arg)
service[i].served++;
served++;
}
#ifndef _WIN32
#ifdef PREFER_POLL
nfdsi += service[i].set->sock_count;
#endif
}
}
#ifndef _WIN32
#ifdef PREFER_POLL
free(fds);
#endif
......
......@@ -1072,7 +1072,11 @@ int sbbs_t::external(const char* cmdline, long mode, const char* startup_dir)
BYTE wwiv_buf[XTRN_IO_BUF_LEN*2];
bool wwiv_flag=false;
char* p;
#ifdef PREFER_POLL
struct pollfd fds[2];
#else
#error select() implementation was removed in 3971ef4d
#endif
xtrn_mode = mode;
lprintf(LOG_DEBUG, "Executing external: %s", cmdline);
......
......@@ -312,15 +312,15 @@ static BOOL read_socket_line(SOCKET sock, char *buffer, size_t buflen, int (*lpr
SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
socklen_t * addrlen, unsigned int timeout, uint32_t flags, void **cb_data)
{
#ifdef _WIN32 // Use select()
#ifdef PREFER_POLL
struct pollfd *fds;
int poll_timeout;
nfds_t scnt = 0;
#else
fd_set read_fs;
struct timeval tv;
struct timeval *tvp;
SOCKET max_sock=0;
#else // Use poll()
struct pollfd *fds;
int poll_timeout;
nfds_t scnt = 0;
#endif
size_t i;
SOCKET ret;
......@@ -333,34 +333,7 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
if (xpms_set->sock_count < 1)
return INVALID_SOCKET;
#ifdef _WIN32
FD_ZERO(&read_fs);
for(i=0; i<xpms_set->sock_count; i++) {
if(xpms_set->socks[i].sock == INVALID_SOCKET)
continue;
FD_SET(xpms_set->socks[i].sock, &read_fs);
if(xpms_set->socks[i].sock >= max_sock)
max_sock=xpms_set->socks[i].sock+1;
}
if(timeout==XPMS_FOREVER)
tvp=NULL;
else {
tv.tv_sec=timeout/1000;
tv.tv_usec=(timeout%1000)*1000;
tvp=&tv;
}
switch(select(max_sock, &read_fs, NULL, NULL, tvp)) {
case 0:
return INVALID_SOCKET;
case -1:
return SOCKET_ERROR;
default:
for(i=0; i<xpms_set->sock_count; i++) {
if(xpms_set->socks[i].sock == INVALID_SOCKET)
continue;
if(FD_ISSET(xpms_set->socks[i].sock, &read_fs)) {
#else
#ifdef PREFER_POLL
fds = calloc(xpms_set->sock_count, sizeof(*fds));
if (fds == NULL)
return INVALID_SOCKET;
......@@ -399,6 +372,33 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
continue;
}
if (fds[scnt++].revents & POLLIN) {
#else
FD_ZERO(&read_fs);
for(i=0; i<xpms_set->sock_count; i++) {
if(xpms_set->socks[i].sock == INVALID_SOCKET)
continue;
FD_SET(xpms_set->socks[i].sock, &read_fs);
if(xpms_set->socks[i].sock >= max_sock)
max_sock=xpms_set->socks[i].sock+1;
}
if(timeout==XPMS_FOREVER)
tvp=NULL;
else {
tv.tv_sec=timeout/1000;
tv.tv_usec=(timeout%1000)*1000;
tvp=&tv;
}
switch(select(max_sock, &read_fs, NULL, NULL, tvp)) {
case 0:
return INVALID_SOCKET;
case -1:
return SOCKET_ERROR;
default:
for(i=0; i<xpms_set->sock_count; i++) {
if(xpms_set->socks[i].sock == INVALID_SOCKET)
continue;
if(FD_ISSET(xpms_set->socks[i].sock, &read_fs)) {
#endif
if(cb_data)
*cb_data=xpms_set->socks[i].cb_data;
......@@ -620,12 +620,12 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
inet_addrtop(addr, hapstr, sizeof(hapstr));
xpms_set->lprintf(LOG_INFO,"%04d * HAPROXY Source [%s]",ret,hapstr);
#ifndef _WIN32
#ifdef PREFER_POLL
free(fds);
#endif
return ret;
} else {
#ifndef _WIN32
#ifdef PREFER_POLL
free(fds);
#endif
return ret;
......@@ -635,7 +635,7 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr,
}
error_return:
#ifndef _WIN32
#ifdef PREFER_POLL
free(fds);
#endif
return INVALID_SOCKET;
......
......@@ -272,7 +272,58 @@ off_t recvfilesocket(int sock, int file, off_t *offset, off_t count)
/* Return true if connected, optionally sets *rd_p to true if read data available */
BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
{
#ifdef _WIN32
#ifdef PREFER_POLL
struct pollfd pfd = {0};
int j, rd;
char ch;
if(rd_p!=NULL)
*rd_p=FALSE;
if(wr_p!=NULL)
*wr_p=FALSE;
if(sock==INVALID_SOCKET)
return(FALSE);
pfd.fd = sock;
pfd.events = POLLIN | POLLHUP;
if (wr_p != NULL)
pfd.events |= POLLOUT;
j = poll(&pfd, 1, timeout);
if (j == 0)
return TRUE;
if (j == 1) {
if (wr_p != NULL && (pfd.revents & POLLOUT))
*wr_p = TRUE;
if (rd_p != NULL && (pfd.revents & POLLIN))
*rd_p = TRUE;
if (pfd.revents & (POLLERR | POLLNVAL))
return FALSE;
if(pfd.revents & (POLLIN | POLLHUP) && (rd_p !=NULL || wr_p==NULL)) {
rd=recv(sock,&ch,1,MSG_PEEK);
if(rd==1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE)) {
if(rd_p!=NULL)
*rd_p=TRUE;
return(TRUE);
}
return FALSE;
}
}
if (j == -1) {
if (errno == EINTR || errno == ENOMEM)
return TRUE;
return FALSE;
}
return TRUE;
#else
char ch;
int i,rd;
fd_set rd_set;
......@@ -328,57 +379,6 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
}
return(FALSE);
#else
struct pollfd pfd = {0};
int j, rd;
char ch;
if(rd_p!=NULL)
*rd_p=FALSE;
if(wr_p!=NULL)
*wr_p=FALSE;
if(sock==INVALID_SOCKET)
return(FALSE);
pfd.fd = sock;
pfd.events = POLLIN | POLLHUP;
if (wr_p != NULL)
pfd.events |= POLLOUT;
j = poll(&pfd, 1, timeout);
if (j == 0)
return TRUE;
if (j == 1) {
if (wr_p != NULL && (pfd.revents & POLLOUT))
*wr_p = TRUE;
if (rd_p != NULL && (pfd.revents & POLLIN))
*rd_p = TRUE;
if (pfd.revents & (POLLERR | POLLNVAL))
return FALSE;
if(pfd.revents & (POLLIN | POLLHUP) && (rd_p !=NULL || wr_p==NULL)) {
rd=recv(sock,&ch,1,MSG_PEEK);
if(rd==1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE)) {
if(rd_p!=NULL)
*rd_p=TRUE;
return(TRUE);
}
return FALSE;
}
}
if (j == -1) {
if (errno == EINTR || errno == ENOMEM)
return TRUE;
return FALSE;
}
return TRUE;
#endif
}
......@@ -391,7 +391,15 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
*/
BOOL socket_readable(SOCKET sock, int timeout)
{
#ifdef _WIN32
#ifdef PREFER_POLL
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout) == 1)
return TRUE;
return FALSE;
#else
fd_set rd_set;
struct timeval tv = {0};
struct timeval *tvp = &tv;
......@@ -413,14 +421,6 @@ BOOL socket_readable(SOCKET sock, int timeout)
}
// Errors and unexpected cases
return TRUE;
#else
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout) == 1)
return TRUE;
return FALSE;
#endif
}
......@@ -433,7 +433,15 @@ BOOL socket_readable(SOCKET sock, int timeout)
*/
BOOL socket_writable(SOCKET sock, int timeout)
{
#ifdef _WIN32
#ifdef PREFER_POLL
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLOUT;
if (poll(&pfd, 1, timeout) == 1)
return TRUE;
return FALSE;
#else
fd_set wr_set;
struct timeval tv = {0};
struct timeval *tvp = &tv;
......@@ -455,14 +463,6 @@ BOOL socket_writable(SOCKET sock, int timeout)
}
// Errors and unexpected cases
return TRUE;
#else
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLOUT;
if (poll(&pfd, 1, timeout) == 1)
return TRUE;
return FALSE;
#endif
}
......@@ -474,7 +474,29 @@ BOOL socket_writable(SOCKET sock, int timeout)
*/
BOOL socket_recvdone(SOCKET sock, int timeout)
{
#ifdef _WIN32
#ifdef PREFER_POLL
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLIN;
char ch;
int rd;
switch (poll(&pfd, 1, timeout)) {
case 1:
if (pfd.revents & (POLLIN | POLLHUP)) {
rd = recv(sock,&ch,1,MSG_PEEK);
if (rd == 1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE))
return FALSE;
return TRUE;
}
return FALSE;
case -1:
if (errno == EINTR || errno == ENOMEM)
return FALSE;
return TRUE;
}
return FALSE;
#else
fd_set rd_set;
struct timeval tv = {0};
struct timeval *tvp = &tv;
......@@ -500,28 +522,6 @@ BOOL socket_recvdone(SOCKET sock, int timeout)
if (rd == 1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE))
return FALSE;
return TRUE;
#else
struct pollfd pfd = {0};
pfd.fd = sock;
pfd.events = POLLIN;
char ch;
int rd;
switch (poll(&pfd, 1, timeout)) {
case 1:
if (pfd.revents & (POLLIN | POLLHUP)) {
rd = recv(sock,&ch,1,MSG_PEEK);
if (rd == 1 || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE))
return FALSE;
return TRUE;
}
return FALSE;
case -1:
if (errno == EINTR || errno == ENOMEM)
return FALSE;
return TRUE;
}
return FALSE;
#endif
}
......