diff --git a/src/ipxwrapper.def b/src/ipxwrapper.def index c3f10ab..934c3d8 100644 --- a/src/ipxwrapper.def +++ b/src/ipxwrapper.def @@ -21,3 +21,4 @@ EXPORTS listen accept WSAAsyncSelect + select diff --git a/src/ipxwrapper.h b/src/ipxwrapper.h index a63c2a7..4ba3a7f 100644 --- a/src/ipxwrapper.h +++ b/src/ipxwrapper.h @@ -188,5 +188,6 @@ int PASCAL r_getpeername(SOCKET fd, struct sockaddr *addr, int *addrlen); int PASCAL r_listen(SOCKET s, int backlog); SOCKET PASCAL r_accept(SOCKET s, struct sockaddr *addr, int *addrlen); int PASCAL r_WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent); +int PASCAL r_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout); #endif /* !IPXWRAPPER_H */ diff --git a/src/ipxwrapper_stubs.txt b/src/ipxwrapper_stubs.txt index d2b308f..b465783 100644 --- a/src/ipxwrapper_stubs.txt +++ b/src/ipxwrapper_stubs.txt @@ -7,7 +7,7 @@ htonl:4 ntohl:4 htons:4 ntohs:4 -select:4 +r_select:4 r_listen:4 r_accept:4 WSACreateEvent:4 diff --git a/src/winsock.c b/src/winsock.c index 6b3d9b2..ce1f172 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -1514,7 +1514,7 @@ int PASCAL ioctlsocket(SOCKET fd, long cmd, u_long *argp) FD_ZERO(&fdset); FD_SET(sock->fd, &fdset); - int r = select(1, &fdset, NULL, NULL, &tv); + int r = r_select(1, &fdset, NULL, NULL, &tv); if(r == -1) { @@ -1779,7 +1779,7 @@ static int _connect_spx(ipx_socket *sock, struct sockaddr_ipx *ipxaddr) .tv_usec = ((wait_until - now) % 1000) * 1000 }; - if(select(1, &fdset, NULL, NULL, &tv) == -1) + if(r_select(1, &fdset, NULL, NULL, &tv) == -1) { closesocket(lookup_fd); free(packet); @@ -1892,7 +1892,7 @@ static int _connect_spx(ipx_socket *sock, struct sockaddr_ipx *ipxaddr) FD_ZERO(&e_fdset); FD_SET(sock->fd, &e_fdset); - if(select(1, NULL, &w_fdset, &e_fdset, NULL) == 1 && FD_ISSET(sock->fd, &w_fdset)) + if(r_select(1, NULL, &w_fdset, &e_fdset, NULL) == 1 && FD_ISSET(sock->fd, &w_fdset)) { goto CONNECTED; } @@ -2374,3 +2374,76 @@ int PASCAL WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent) return r_WSAAsyncSelect(s, hWnd, wMsg, lEvent); } + +int PASCAL select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) +{ + if(ipx_use_pcap) + { + /* Can't do anything when using pcap since there isn't a socket + * to wait on for sending. + */ + return r_select(nfds, readfds, writefds, exceptfds, timeout); + } + + bool writefds_bodge = false; + + fd_set writefds_pulled; + FD_ZERO(&writefds_pulled); + + if(writefds != NULL) + { + /* Search for any IPX sockets being referenced in writefds... */ + lock_sockets(); + + ipx_socket *sock, *tmp; + HASH_ITER(hh, sockets, sock, tmp) + { + if(!(sock->flags & IPX_IS_SPX) && FD_ISSET(sock->fd, writefds)) + { + /* Found one! Remove it and stash it for later. */ + writefds_bodge = true; + FD_SET(sock->fd, &writefds_pulled); + FD_CLR(sock->fd, writefds); + } + } + + unlock_sockets(); + } + + if(writefds_bodge) + { + /* At least one IPX socket was removed from writefds, put the + * private UDP socket there instead since that is what actually + * matters for sending. + */ + FD_SET(private_socket, writefds); + } + + int sret = r_select(nfds, readfds, writefds, exceptfds, timeout); + + if(sret > 0 && writefds_bodge && FD_ISSET(private_socket, writefds)) + { + /* We munged writefds and private_socket is still there, take it + * out and re-add any of the IPX sockets we removed earlier. + */ + + FD_CLR(private_socket, writefds); + --sret; + + lock_sockets(); + + ipx_socket *sock, *tmp; + HASH_ITER(hh, sockets, sock, tmp) + { + if(FD_ISSET(sock->fd, &writefds_pulled)) + { + FD_SET(sock->fd, writefds); + ++sret; + } + } + + unlock_sockets(); + } + + return sret; +} diff --git a/src/wsock32_stubs.txt b/src/wsock32_stubs.txt index 75450c4..6131143 100644 --- a/src/wsock32_stubs.txt +++ b/src/wsock32_stubs.txt @@ -15,7 +15,7 @@ ntohl ntohs recv:0 recvfrom:0 -select +select:0 send:0 sendto:0 setsockopt:0