diff --git a/src/xpdev/multisock.c b/src/xpdev/multisock.c index 6de32e108959e21a94c1c2caa3bd87affdcc213b..e6483f1a2b202df05a3347b706258a02c3ca76be 100644 --- a/src/xpdev/multisock.c +++ b/src/xpdev/multisock.c @@ -255,22 +255,13 @@ static void btox(char *hexstr, const char *srcbuf, size_t srcbuflen, size_t hexs static BOOL read_socket(SOCKET sock, char *buffer, size_t len, int (*lprintf)(int level, const char *fmt, ...)) { - fd_set socket_set; - struct timeval tv; size_t i; - int j,rd; + int rd; unsigned char ch; char err[128]; for (i=0;i<len;i++) { - FD_ZERO(&socket_set); - FD_SET(sock,&socket_set); - - // We'll wait 1 secs to read from the socket. - tv.tv_sec=1; - tv.tv_usec=0; - - if((j=select(sock+1,&socket_set,NULL,NULL,&tv))>0) { + if (socket_readable(sock, 1000)) { rd = recv(sock,&ch,1,0); if (rd == 0) { lprintf(LOG_WARNING,"%04d multisock read_socket() - remote closed the connection",sock); @@ -284,13 +275,10 @@ static BOOL read_socket(SOCKET sock, char *buffer, size_t len, int (*lprintf)(in return FALSE; } - } else if (j==0) { + } else { lprintf(LOG_WARNING,"%04d multisock read_socket() - No data?",sock); return FALSE; - } else { - lprintf(LOG_WARNING,"%04d multisock read_socket() - select() returned [%d] with error [%s].",sock,j,socket_strerror(socket_errno,err,sizeof(err))); - return FALSE; } } @@ -324,11 +312,17 @@ 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() fd_set read_fs; - size_t i; 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; char hapstr[128]; char haphex[256]; @@ -336,6 +330,10 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr, long l; void *vp; + 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) @@ -362,6 +360,41 @@ SOCKET DLLCALL xpms_accept(struct xpms_set *xpms_set, union xp_sockaddr * addr, if(xpms_set->socks[i].sock == INVALID_SOCKET) continue; if(FD_ISSET(xpms_set->socks[i].sock, &read_fs)) { +#else + fds = calloc(xpms_set->sock_count, sizeof(*fds)); + for (i = 0; i < xpms_set->sock_count; i++) { + if (xpms_set->socks[i].sock == INVALID_SOCKET) + continue; + fds[scnt].fd = xpms_set->socks[i].sock; + fds[scnt].events = POLLIN; + scnt++; + } + + if (timeout == XPMS_FOREVER) + poll_timeout = -1; + else if (timeout > INT_MAX) + poll_timeout = INT_MAX; + else + poll_timeout = timeout; + + switch (poll(fds, scnt, timeout)) { + case 0: + return INVALID_SOCKET; + case -1: + return SOCKET_ERROR; + default: + scnt = 0; + for(i=0; i<xpms_set->sock_count; i++) { + if(xpms_set->socks[i].sock == INVALID_SOCKET) + continue; + if ((fds[scnt].revents & POLLIN) == 0) { + closesocket(xpms_set->socks[i].sock); + xpms_set->lprintf(LOG_ERR, "%04d * Listening socket went bad", xpms_set->socks[i].sock); + xpms_set->socks[i].sock = INVALID_SOCKET; + continue; + } + else { +#endif if(cb_data) *cb_data=xpms_set->socks[i].cb_data; ret = accept(xpms_set->socks[i].sock, &addr->addr, addrlen); diff --git a/src/xpdev/sockwrap.c b/src/xpdev/sockwrap.c index d45fd475a3bf37f4d4b5068cbec8470b4b5b70cb..e0abe847474ec593c9b6d740fb68d23a54c04b25 100644 --- a/src/xpdev/sockwrap.c +++ b/src/xpdev/sockwrap.c @@ -272,6 +272,7 @@ 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 char ch; int i,rd; fd_set rd_set; @@ -327,6 +328,42 @@ BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout) } return(FALSE); +#else + struct pollfd pfd = {0}; + int j; + + 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; + 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; + return TRUE; + } + + if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) + return FALSE; + } + return FALSE; +#endif } /* @@ -494,32 +531,19 @@ int retry_bind(SOCKET s, const struct sockaddr *addr, socklen_t addrlen int nonblocking_connect(SOCKET sock, struct sockaddr* addr, size_t size, unsigned timeout) { int result; + socklen_t optlen; result=connect(sock, addr, size); if(result==SOCKET_ERROR) { result=ERROR_VALUE; if(result==EWOULDBLOCK || result==EINPROGRESS) { - fd_set wsocket_set; - fd_set esocket_set; - struct timeval tv; - socklen_t optlen=sizeof(result); - tv.tv_sec = timeout; - tv.tv_usec = 0; - FD_ZERO(&wsocket_set); - FD_SET(sock,&wsocket_set); - FD_ZERO(&esocket_set); - FD_SET(sock,&esocket_set); - switch(select(sock+1,NULL,&wsocket_set,&esocket_set,&tv)) { - case 1: - if(getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&result, &optlen)==SOCKET_ERROR) - result=ERROR_VALUE; - break; - case 0: - break; - case SOCKET_ERROR: + if (socket_writable(sock, timeout * 1000)) { + result = 0; + } + else { + if(getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&result, &optlen)==SOCKET_ERROR) result=ERROR_VALUE; - break; } } }