Added support for using select() instead of poll().
This commit is contained in:
parent
c1797c6867
commit
11e29ff7eb
15
acinclude.m4
15
acinclude.m4
|
@ -75,6 +75,21 @@ AC_DEFUN([ACX_CHECK_CXX_STDLIB], [
|
||||||
fi
|
fi
|
||||||
])dnl ACX_CHECK_CXX_STDLIB
|
])dnl ACX_CHECK_CXX_STDLIB
|
||||||
|
|
||||||
|
AC_DEFUN([ACX_CHECK_POLL], [
|
||||||
|
AC_MSG_CHECKING([for poll])
|
||||||
|
AC_TRY_LINK([#include <sys/poll.h>],
|
||||||
|
[struct pollfd ufds[] = { 0, POLLIN, 0 }; poll(ufds, 1, 10);],
|
||||||
|
acx_poll_ok=yes, acx_poll_ok=no)
|
||||||
|
AC_MSG_RESULT($acx_poll_ok)
|
||||||
|
if test x"$acx_poll_ok" = xyes; then
|
||||||
|
ifelse([$1],,AC_DEFINE(HAVE_POLL,1,[Define if you have the `poll' function.]),[$1])
|
||||||
|
:
|
||||||
|
else
|
||||||
|
acx_poll_ok=no
|
||||||
|
$2
|
||||||
|
fi
|
||||||
|
])dnl ACX_CHECK_POLL
|
||||||
|
|
||||||
dnl The following macros are from http://www.gnu.org/software/ac-archive/
|
dnl The following macros are from http://www.gnu.org/software/ac-archive/
|
||||||
dnl which distributes them under the following license:
|
dnl which distributes them under the following license:
|
||||||
dnl
|
dnl
|
||||||
|
|
|
@ -72,6 +72,8 @@ AC_FUNC_STRFTIME
|
||||||
AC_CHECK_FUNCS(gmtime_r)
|
AC_CHECK_FUNCS(gmtime_r)
|
||||||
AC_CHECK_FUNCS(getpwuid_r)
|
AC_CHECK_FUNCS(getpwuid_r)
|
||||||
AC_CHECK_FUNCS(vsnprintf)
|
AC_CHECK_FUNCS(vsnprintf)
|
||||||
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
|
ACX_CHECK_POLL
|
||||||
dnl use AC_REPLACE_FUNCS() for stuff in string.h
|
dnl use AC_REPLACE_FUNCS() for stuff in string.h
|
||||||
|
|
||||||
dnl checks for system services
|
dnl checks for system services
|
||||||
|
|
|
@ -51,6 +51,7 @@ struct protoent FAR * (PASCAL FAR *CNetwork::getprotobyname)(const char FAR * na
|
||||||
int (PASCAL FAR *CNetwork::getsockerror)(void);
|
int (PASCAL FAR *CNetwork::getsockerror)(void);
|
||||||
int (PASCAL FAR *CNetwork::gethosterror)(void);
|
int (PASCAL FAR *CNetwork::gethosterror)(void);
|
||||||
int (PASCAL FAR *CNetwork::setblocking)(CNetwork::Socket s, bool blocking);
|
int (PASCAL FAR *CNetwork::setblocking)(CNetwork::Socket s, bool blocking);
|
||||||
|
int (PASCAL FAR *CNetwork::setnodelay)(CNetwork::Socket s, bool blocking);
|
||||||
|
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
|
|
||||||
|
@ -226,79 +227,11 @@ CNetwork::init2(
|
||||||
read = read2;
|
read = read2;
|
||||||
write = write2;
|
write = write2;
|
||||||
setblocking = setblocking2;
|
setblocking = setblocking2;
|
||||||
|
setnodelay = setnodelay2;
|
||||||
|
|
||||||
s_networkModule = module;
|
s_networkModule = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PASCAL FAR
|
|
||||||
CNetwork::poll2(PollEntry fd[], int nfds, int timeout)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// prepare sets for select
|
|
||||||
fd_set readSet, writeSet, errSet;
|
|
||||||
fd_set* readSetP = NULL;
|
|
||||||
fd_set* writeSetP = NULL;
|
|
||||||
fd_set* errSetP = NULL;
|
|
||||||
FD_ZERO(&readSet);
|
|
||||||
FD_ZERO(&writeSet);
|
|
||||||
FD_ZERO(&errSet);
|
|
||||||
for (i = 0; i < nfds; ++i) {
|
|
||||||
if (fd[i].events & kPOLLIN) {
|
|
||||||
FD_SET(fd[i].fd, &readSet);
|
|
||||||
readSetP = &readSet;
|
|
||||||
}
|
|
||||||
if (fd[i].events & kPOLLOUT) {
|
|
||||||
FD_SET(fd[i].fd, &writeSet);
|
|
||||||
writeSetP = &writeSet;
|
|
||||||
}
|
|
||||||
if (true) {
|
|
||||||
FD_SET(fd[i].fd, &errSet);
|
|
||||||
errSetP = &errSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepare timeout for select
|
|
||||||
struct timeval timeout2;
|
|
||||||
struct timeval* timeout2P;
|
|
||||||
if (timeout < 0) {
|
|
||||||
timeout2P = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
timeout2P = &timeout2;
|
|
||||||
timeout2.tv_sec = timeout / 1000;
|
|
||||||
timeout2.tv_usec = 1000 * (timeout % 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the select. note that winsock ignores the first argument.
|
|
||||||
int n = select(0, readSetP, writeSetP, errSetP, timeout2P);
|
|
||||||
|
|
||||||
// handle results
|
|
||||||
if (n == Error) {
|
|
||||||
return Error;
|
|
||||||
}
|
|
||||||
if (n == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n = 0;
|
|
||||||
for (i = 0; i < nfds; ++i) {
|
|
||||||
fd[i].revents = 0;
|
|
||||||
if (FD_ISSET(fd[i].fd, &readSet)) {
|
|
||||||
fd[i].revents |= kPOLLIN;
|
|
||||||
}
|
|
||||||
if (FD_ISSET(fd[i].fd, &writeSet)) {
|
|
||||||
fd[i].revents |= kPOLLOUT;
|
|
||||||
}
|
|
||||||
if (FD_ISSET(fd[i].fd, &errSet)) {
|
|
||||||
fd[i].revents |= kPOLLERR;
|
|
||||||
}
|
|
||||||
if (fd[i].revents != 0) {
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t PASCAL FAR
|
ssize_t PASCAL FAR
|
||||||
CNetwork::read2(Socket s, void FAR* buf, size_t len)
|
CNetwork::read2(Socket s, void FAR* buf, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -318,17 +251,39 @@ CNetwork::setblocking2(CNetwork::Socket s, bool blocking)
|
||||||
return ioctl(s, FIONBIO, &flag);
|
return ioctl(s, FIONBIO, &flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PASCAL FAR
|
||||||
|
CNetwork::setnodelay2(CNetwork::Socket s, bool nodelay)
|
||||||
|
{
|
||||||
|
BOOL flag = nodelay ? 1 : 0;
|
||||||
|
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNIX_LIKE
|
#if UNIX_LIKE
|
||||||
|
|
||||||
#include <unistd.h>
|
#if HAVE_SYS_TYPES_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_SYS_STAT_H
|
||||||
|
# include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#if !defined(TCP_NODELAY) || !defined(SOL_TCP)
|
||||||
|
# include <netinet/tcp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME -- use reentrant versions of non-reentrant functions
|
// FIXME -- use reentrant versions of non-reentrant functions
|
||||||
|
|
||||||
|
const int CNetwork::Error = -1;
|
||||||
|
const CNetwork::Socket CNetwork::Null = -1;
|
||||||
|
|
||||||
#define setfunc(var, name, type) var = (type)::name
|
#define setfunc(var, name, type) var = (type)::name
|
||||||
|
|
||||||
UInt32
|
UInt32
|
||||||
|
@ -355,30 +310,73 @@ CNetwork::swapntohs(UInt16 v)
|
||||||
return ntohs(v);
|
return ntohs(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
void
|
||||||
int
|
CNetwork::init()
|
||||||
myerrno()
|
{
|
||||||
|
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen));
|
||||||
|
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen));
|
||||||
|
setfunc(close, close, int (PASCAL FAR *)(Socket s));
|
||||||
|
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
|
||||||
|
setfunc(ioctl, ioctl, int (PASCAL FAR *)(Socket s, int cmd, void FAR *));
|
||||||
|
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
|
||||||
|
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
|
||||||
|
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
|
||||||
|
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
|
||||||
|
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
|
||||||
|
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog));
|
||||||
|
#if HAVE_POLL
|
||||||
|
setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
|
||||||
|
#else
|
||||||
|
setfunc(poll, CNetwork::poll2, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
|
||||||
|
#endif
|
||||||
|
setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len));
|
||||||
|
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));
|
||||||
|
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen));
|
||||||
|
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags));
|
||||||
|
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen));
|
||||||
|
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen));
|
||||||
|
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how));
|
||||||
|
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol));
|
||||||
|
setfunc(write, write, ssize_t (PASCAL FAR *)(CNetwork::Socket s, const void FAR * buf, size_t len));
|
||||||
|
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
|
||||||
|
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
|
||||||
|
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto));
|
||||||
|
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
|
||||||
|
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto));
|
||||||
|
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name));
|
||||||
|
gethostname = gethostname2;
|
||||||
|
getsockerror = getsockerror2;
|
||||||
|
gethosterror = gethosterror2;
|
||||||
|
setblocking = setblocking2;
|
||||||
|
setnodelay = setnodelay2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CNetwork::cleanup()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
int PASCAL FAR
|
||||||
|
CNetwork::gethostname2(char* name, int namelen)
|
||||||
|
{
|
||||||
|
return ::gethostname(name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PASCAL FAR
|
||||||
|
CNetwork::getsockerror2(void)
|
||||||
{
|
{
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
int PASCAL FAR
|
||||||
int
|
CNetwork::gethosterror2(void)
|
||||||
myherrno()
|
|
||||||
{
|
{
|
||||||
return h_errno;
|
return h_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
int PASCAL FAR
|
||||||
int
|
CNetwork::setblocking2(CNetwork::Socket s, bool blocking)
|
||||||
mygethostname(char* name, int namelen)
|
|
||||||
{
|
|
||||||
return gethostname(name, namelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int
|
|
||||||
mysetblocking(CNetwork::Socket s, bool blocking)
|
|
||||||
{
|
{
|
||||||
int mode = fcntl(s, F_GETFL, 0);
|
int mode = fcntl(s, F_GETFL, 0);
|
||||||
if (mode == -1) {
|
if (mode == -1) {
|
||||||
|
@ -396,49 +394,111 @@ mysetblocking(CNetwork::Socket s, bool blocking)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int CNetwork::Error = -1;
|
int PASCAL FAR
|
||||||
const CNetwork::Socket CNetwork::Null = -1;
|
CNetwork::setnodelay2(CNetwork::Socket s, bool nodelay)
|
||||||
|
|
||||||
void
|
|
||||||
CNetwork::init()
|
|
||||||
{
|
{
|
||||||
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen));
|
int flag = nodelay ? 1 : 0;
|
||||||
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen));
|
setsockopt(s, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
setfunc(close, close, int (PASCAL FAR *)(Socket s));
|
}
|
||||||
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
|
|
||||||
setfunc(ioctl, ioctl, int (PASCAL FAR *)(Socket s, int cmd, void FAR *));
|
#endif
|
||||||
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
|
|
||||||
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
|
#if WINDOWS_LIKE || !HAVE_POLL
|
||||||
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
|
|
||||||
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
|
#if HAVE_SYS_SELECT_H
|
||||||
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
|
# include <sys/select.h>
|
||||||
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog));
|
#endif
|
||||||
setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
|
#if HAVE_SYS_TIME_H
|
||||||
setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len));
|
# include <sys/time.h>
|
||||||
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));
|
#endif
|
||||||
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen));
|
#if HAVE_SYS_TYPES_H
|
||||||
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags));
|
# include <sys/types.h>
|
||||||
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen));
|
#endif
|
||||||
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen));
|
#if HAVE_UNISTD_H
|
||||||
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how));
|
# include <unistd.h>
|
||||||
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol));
|
#endif
|
||||||
setfunc(write, write, ssize_t (PASCAL FAR *)(CNetwork::Socket s, const void FAR * buf, size_t len));
|
|
||||||
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
|
int PASCAL FAR
|
||||||
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
|
CNetwork::poll2(PollEntry fd[], int nfds, int timeout)
|
||||||
setfunc(gethostname, mygethostname, int (PASCAL FAR *)(char FAR * name, int namelen));
|
{
|
||||||
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto));
|
int i;
|
||||||
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
|
|
||||||
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto));
|
// prepare sets for select
|
||||||
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name));
|
int n = 0;
|
||||||
setfunc(getsockerror, myerrno, int (PASCAL FAR *)(void));
|
fd_set readSet, writeSet, errSet;
|
||||||
setfunc(gethosterror, myherrno, int (PASCAL FAR *)(void));
|
fd_set* readSetP = NULL;
|
||||||
setfunc(setblocking, mysetblocking, int (PASCAL FAR *)(Socket, bool));
|
fd_set* writeSetP = NULL;
|
||||||
}
|
fd_set* errSetP = NULL;
|
||||||
|
FD_ZERO(&readSet);
|
||||||
void
|
FD_ZERO(&writeSet);
|
||||||
CNetwork::cleanup()
|
FD_ZERO(&errSet);
|
||||||
{
|
for (i = 0; i < nfds; ++i) {
|
||||||
// do nothing
|
if (fd[i].events & kPOLLIN) {
|
||||||
|
FD_SET(fd[i].fd, &readSet);
|
||||||
|
readSetP = &readSet;
|
||||||
|
if (fd[i].fd > n) {
|
||||||
|
n = fd[i].fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fd[i].events & kPOLLOUT) {
|
||||||
|
FD_SET(fd[i].fd, &writeSet);
|
||||||
|
writeSetP = &writeSet;
|
||||||
|
if (fd[i].fd > n) {
|
||||||
|
n = fd[i].fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (true) {
|
||||||
|
FD_SET(fd[i].fd, &errSet);
|
||||||
|
errSetP = &errSet;
|
||||||
|
if (fd[i].fd > n) {
|
||||||
|
n = fd[i].fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare timeout for select
|
||||||
|
struct timeval timeout2;
|
||||||
|
struct timeval* timeout2P;
|
||||||
|
if (timeout < 0) {
|
||||||
|
timeout2P = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timeout2P = &timeout2;
|
||||||
|
timeout2.tv_sec = timeout / 1000;
|
||||||
|
timeout2.tv_usec = 1000 * (timeout % 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the select. note that winsock ignores the first argument.
|
||||||
|
n = select((SELECT_TYPE_ARG1) n + 1,
|
||||||
|
SELECT_TYPE_ARG234 readSetP,
|
||||||
|
SELECT_TYPE_ARG234 writeSetP,
|
||||||
|
SELECT_TYPE_ARG234 errSetP,
|
||||||
|
SELECT_TYPE_ARG5 timeout2P);
|
||||||
|
|
||||||
|
// handle results
|
||||||
|
if (n == Error) {
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n = 0;
|
||||||
|
for (i = 0; i < nfds; ++i) {
|
||||||
|
fd[i].revents = 0;
|
||||||
|
if (FD_ISSET(fd[i].fd, &readSet)) {
|
||||||
|
fd[i].revents |= kPOLLIN;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(fd[i].fd, &writeSet)) {
|
||||||
|
fd[i].revents |= kPOLLOUT;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(fd[i].fd, &errSet)) {
|
||||||
|
fd[i].revents |= kPOLLERR;
|
||||||
|
}
|
||||||
|
if (fd[i].revents != 0) {
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,15 +17,22 @@
|
||||||
|
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
|
|
||||||
|
#if HAVE_SYS_TYPES_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_POLL
|
||||||
|
# include <sys/poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WINDOWS_LIKE
|
#if WINDOWS_LIKE
|
||||||
// declare no functions in winsock2
|
// declare no functions in winsock2
|
||||||
# define INCL_WINSOCK_API_PROTOTYPES 0
|
# define INCL_WINSOCK_API_PROTOTYPES 0
|
||||||
# define INCL_WINSOCK_API_TYPEDEFS 0
|
# define INCL_WINSOCK_API_TYPEDEFS 0
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
typedef int ssize_t;
|
typedef int ssize_t;
|
||||||
# if !defined(SOL_TCP)
|
|
||||||
# define SOL_TCP IPPROTO_TCP
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
# undef FAR
|
# undef FAR
|
||||||
# undef PASCAL
|
# undef PASCAL
|
||||||
|
@ -34,15 +41,8 @@ typedef int ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNIX_LIKE
|
#if UNIX_LIKE
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/poll.h>
|
|
||||||
# include <sys/socket.h>
|
|
||||||
# include <netdb.h>
|
# include <netdb.h>
|
||||||
# include <netinet/in.h>
|
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# if !defined(TCP_NODELAY) || !defined(SOL_TCP)
|
|
||||||
# include <netinet/tcp.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Networking functions
|
//! Networking functions
|
||||||
|
@ -53,7 +53,13 @@ public:
|
||||||
typedef SOCKET Socket;
|
typedef SOCKET Socket;
|
||||||
typedef struct sockaddr Address;
|
typedef struct sockaddr Address;
|
||||||
typedef int AddressLength;
|
typedef int AddressLength;
|
||||||
typedef BOOL TCPNoDelayType;
|
#elif UNIX_LIKE
|
||||||
|
typedef int Socket;
|
||||||
|
typedef struct sockaddr Address;
|
||||||
|
typedef socklen_t AddressLength;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WINDOWS_LIKE || !HAVE_POLL
|
||||||
class PollEntry {
|
class PollEntry {
|
||||||
public:
|
public:
|
||||||
Socket fd;
|
Socket fd;
|
||||||
|
@ -66,12 +72,8 @@ public:
|
||||||
kPOLLERR = 4,
|
kPOLLERR = 4,
|
||||||
kPOLLNVAL = 8
|
kPOLLNVAL = 8
|
||||||
};
|
};
|
||||||
#elif UNIX_LIKE
|
#else
|
||||||
typedef int Socket;
|
|
||||||
typedef struct sockaddr Address;
|
|
||||||
typedef socklen_t AddressLength;
|
|
||||||
typedef struct pollfd PollEntry;
|
typedef struct pollfd PollEntry;
|
||||||
typedef int TCPNoDelayType;
|
|
||||||
enum {
|
enum {
|
||||||
kPOLLIN = POLLIN,
|
kPOLLIN = POLLIN,
|
||||||
kPOLLOUT = POLLOUT,
|
kPOLLOUT = POLLOUT,
|
||||||
|
@ -183,17 +185,39 @@ public:
|
||||||
//! Set socket to (non-)blocking operation
|
//! Set socket to (non-)blocking operation
|
||||||
static int (PASCAL FAR *setblocking)(CNetwork::Socket s, bool blocking);
|
static int (PASCAL FAR *setblocking)(CNetwork::Socket s, bool blocking);
|
||||||
|
|
||||||
#if WINDOWS_LIKE
|
//! Turn Nagle algorithm on or off on socket
|
||||||
|
/*!
|
||||||
|
Set socket to send messages immediately (true) or to collect small
|
||||||
|
messages into one packet (false).
|
||||||
|
*/
|
||||||
|
static int (PASCAL FAR *setnodelay)(CNetwork::Socket s, bool nodelay);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if WINDOWS_LIKE
|
||||||
|
#define SELECT_TYPE_ARG1 int
|
||||||
|
#define SELECT_TYPE_ARG234 (fd_set *)
|
||||||
|
#define SELECT_TYPE_ARG5 (struct timeval *)
|
||||||
static void init2(HMODULE);
|
static void init2(HMODULE);
|
||||||
static int PASCAL FAR poll2(PollEntry[], int nfds, int timeout);
|
|
||||||
static ssize_t PASCAL FAR read2(Socket s, void FAR * buf, size_t len);
|
static ssize_t PASCAL FAR read2(Socket s, void FAR * buf, size_t len);
|
||||||
static ssize_t PASCAL FAR write2(Socket s, const void FAR * buf, size_t len);
|
static ssize_t PASCAL FAR write2(Socket s, const void FAR * buf, size_t len);
|
||||||
static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking);
|
static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking);
|
||||||
|
static int PASCAL FAR setnodelay2(CNetwork::Socket s, bool nodelay);
|
||||||
static int (PASCAL FAR *WSACleanup)(void);
|
static int (PASCAL FAR *WSACleanup)(void);
|
||||||
static int (PASCAL FAR *__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *);
|
static int (PASCAL FAR *__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *);
|
||||||
static int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
|
static int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if UNIX_LIKE
|
||||||
|
static int PASCAL FAR gethostname2(char FAR * name, int namelen);
|
||||||
|
static int PASCAL FAR getsockerror2(void);
|
||||||
|
static int PASCAL FAR gethosterror2(void);
|
||||||
|
static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking);
|
||||||
|
static int PASCAL FAR setnodelay2(CNetwork::Socket s, bool nodelay);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WINDOWS_LIKE || !HAVE_POLL
|
||||||
|
static int PASCAL FAR poll2(PollEntry[], int nfds, int timeout);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -208,8 +208,7 @@ CTCPSocket::init()
|
||||||
// turn off Nagle algorithm. we send lots of very short messages
|
// turn off Nagle algorithm. we send lots of very short messages
|
||||||
// that should be sent without (much) delay. for example, the
|
// that should be sent without (much) delay. for example, the
|
||||||
// mouse motion messages are much less useful if they're delayed.
|
// mouse motion messages are much less useful if they're delayed.
|
||||||
CNetwork::TCPNoDelayType flag = 1;
|
CNetwork::setnodelay(m_fd, true);
|
||||||
CNetwork::setsockopt(m_fd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -32,7 +32,22 @@
|
||||||
# include <X11/Xutil.h>
|
# include <X11/Xutil.h>
|
||||||
#endif
|
#endif
|
||||||
#if UNIX_LIKE
|
#if UNIX_LIKE
|
||||||
#include <sys/poll.h>
|
# if HAVE_POLL
|
||||||
|
# include <sys/poll.h>
|
||||||
|
# else
|
||||||
|
# if HAVE_SYS_SELECT_H
|
||||||
|
# include <sys/select.h>
|
||||||
|
# endif
|
||||||
|
# if HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
# endif
|
||||||
|
# if HAVE_SYS_TYPES_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
# endif
|
||||||
|
# if HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -240,19 +255,48 @@ CXWindowsScreen::mainLoop()
|
||||||
|
|
||||||
// use poll() to wait for a message from the X server or for timeout.
|
// use poll() to wait for a message from the X server or for timeout.
|
||||||
// this is a good deal more efficient than polling and sleeping.
|
// this is a good deal more efficient than polling and sleeping.
|
||||||
|
#if HAVE_POLL
|
||||||
struct pollfd pfds[1];
|
struct pollfd pfds[1];
|
||||||
pfds[0].fd = ConnectionNumber(m_display);
|
pfds[0].fd = ConnectionNumber(m_display);
|
||||||
pfds[0].events = POLLIN;
|
pfds[0].events = POLLIN;
|
||||||
|
#endif
|
||||||
while (!m_stop) {
|
while (!m_stop) {
|
||||||
// compute timeout to next timer
|
// compute timeout to next timer
|
||||||
|
#if HAVE_POLL
|
||||||
int timeout = (m_timers.empty() ? -1 :
|
int timeout = (m_timers.empty() ? -1 :
|
||||||
static_cast<int>(1000.0 * m_timers.top()));
|
static_cast<int>(1000.0 * m_timers.top()));
|
||||||
|
#else
|
||||||
|
struct timeval timeout;
|
||||||
|
struct timeval* timeoutPtr;
|
||||||
|
if (m_timers.empty()) {
|
||||||
|
timeoutPtr = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timeout.tv_sec = static_cast<int>(m_timers.top());
|
||||||
|
timeout.tv_usec = static_cast<int>(1.0e+6 *
|
||||||
|
(m_timers.top() - timeout.tv_sec));
|
||||||
|
timeoutPtr = &timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize file descriptor sets
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(ConnectionNumber(m_display), &rfds);
|
||||||
|
#endif
|
||||||
|
|
||||||
// wait for message from X server or for timeout. also check
|
// wait for message from X server or for timeout. also check
|
||||||
// if the thread has been cancelled. poll() should return -1
|
// if the thread has been cancelled. poll() should return -1
|
||||||
// with EINTR when the thread is cancelled.
|
// with EINTR when the thread is cancelled.
|
||||||
m_mutex.unlock();
|
m_mutex.unlock();
|
||||||
|
#if HAVE_POLL
|
||||||
poll(pfds, 1, timeout);
|
poll(pfds, 1, timeout);
|
||||||
|
#else
|
||||||
|
select(ConnectionNumber(m_display) + 1,
|
||||||
|
SELECT_TYPE_ARG234 &rfds,
|
||||||
|
SELECT_TYPE_ARG234 NULL,
|
||||||
|
SELECT_TYPE_ARG234 NULL,
|
||||||
|
SELECT_TYPE_ARG5 timeoutPtr);
|
||||||
|
#endif
|
||||||
CThread::testCancel();
|
CThread::testCancel();
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue