Made all arch sockets non-blocking.
This commit is contained in:
parent
75cafe65a6
commit
d6ec331b09
|
@ -435,10 +435,10 @@ CArch::acceptSocket(CArchSocket s, CArchNetAddress* addr)
|
||||||
return m_net->acceptSocket(s, addr);
|
return m_net->acceptSocket(s, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CArch::connectSocket(CArchSocket s, CArchNetAddress name)
|
CArch::connectSocket(CArchSocket s, CArchNetAddress name)
|
||||||
{
|
{
|
||||||
m_net->connectSocket(s, name);
|
return m_net->connectSocket(s, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -471,12 +471,6 @@ CArch::throwErrorOnSocket(CArchSocket s)
|
||||||
m_net->throwErrorOnSocket(s);
|
m_net->throwErrorOnSocket(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
CArch::setBlockingOnSocket(CArchSocket s, bool blocking)
|
|
||||||
{
|
|
||||||
return m_net->setBlockingOnSocket(s, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CArch::setNoDelayOnSocket(CArchSocket s, bool noDelay)
|
CArch::setNoDelayOnSocket(CArchSocket s, bool noDelay)
|
||||||
{
|
{
|
||||||
|
|
|
@ -132,14 +132,13 @@ public:
|
||||||
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
||||||
virtual void listenOnSocket(CArchSocket s);
|
virtual void listenOnSocket(CArchSocket s);
|
||||||
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
||||||
virtual void connectSocket(CArchSocket s, CArchNetAddress name);
|
virtual bool connectSocket(CArchSocket s, CArchNetAddress name);
|
||||||
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
||||||
virtual void unblockPollSocket(CArchThread thread);
|
virtual void unblockPollSocket(CArchThread thread);
|
||||||
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
||||||
virtual size_t writeSocket(CArchSocket s,
|
virtual size_t writeSocket(CArchSocket s,
|
||||||
const void* buf, size_t len);
|
const void* buf, size_t len);
|
||||||
virtual void throwErrorOnSocket(CArchSocket);
|
virtual void throwErrorOnSocket(CArchSocket);
|
||||||
virtual bool setBlockingOnSocket(CArchSocket, bool blocking);
|
|
||||||
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
||||||
virtual std::string getHostName();
|
virtual std::string getHostName();
|
||||||
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
||||||
|
|
|
@ -69,17 +69,22 @@ CArchNetworkBSD::~CArchNetworkBSD()
|
||||||
CArchSocket
|
CArchSocket
|
||||||
CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
|
CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
|
||||||
{
|
{
|
||||||
// allocate socket object
|
|
||||||
CArchSocketImpl* newSocket = new CArchSocketImpl;
|
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
int fd = socket(s_family[family], s_type[type], 0);
|
int fd = socket(s_family[family], s_type[type], 0);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
setBlockingOnSocket(fd, false);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
close(fd);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate socket object
|
||||||
|
CArchSocketImpl* newSocket = new CArchSocketImpl;
|
||||||
newSocket->m_fd = fd;
|
newSocket->m_fd = fd;
|
||||||
newSocket->m_connected = false;
|
|
||||||
newSocket->m_refCount = 1;
|
newSocket->m_refCount = 1;
|
||||||
return newSocket;
|
return newSocket;
|
||||||
}
|
}
|
||||||
|
@ -108,23 +113,14 @@ CArchNetworkBSD::closeSocket(CArchSocket s)
|
||||||
|
|
||||||
// close the socket if necessary
|
// close the socket if necessary
|
||||||
if (doClose) {
|
if (doClose) {
|
||||||
do {
|
|
||||||
if (close(s->m_fd) == -1) {
|
if (close(s->m_fd) == -1) {
|
||||||
// close failed
|
// close failed. restore the last ref and throw.
|
||||||
int err = errno;
|
int err = errno;
|
||||||
if (err == EINTR) {
|
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the last ref and throw
|
|
||||||
ARCH->lockMutex(m_mutex);
|
ARCH->lockMutex(m_mutex);
|
||||||
++s->m_refCount;
|
++s->m_refCount;
|
||||||
ARCH->unlockMutex(m_mutex);
|
ARCH->unlockMutex(m_mutex);
|
||||||
throwError(err);
|
throwError(err);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
delete s;
|
delete s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,26 +187,31 @@ CArchNetworkBSD::acceptSocket(CArchSocket s, CArchNetAddress* addr)
|
||||||
*addr = new CArchNetAddressImpl;
|
*addr = new CArchNetAddressImpl;
|
||||||
|
|
||||||
// accept on socket
|
// accept on socket
|
||||||
int fd;
|
int fd = accept(s->m_fd, &(*addr)->m_addr, &(*addr)->m_len);
|
||||||
do {
|
|
||||||
fd = accept(s->m_fd, &(*addr)->m_addr, &(*addr)->m_len);
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
int err = errno;
|
int err = errno;
|
||||||
if (err == EINTR) {
|
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
delete newSocket;
|
delete newSocket;
|
||||||
delete *addr;
|
delete *addr;
|
||||||
*addr = NULL;
|
*addr = NULL;
|
||||||
|
if (err == EAGAIN) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
throwError(err);
|
throwError(err);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
|
try {
|
||||||
|
setBlockingOnSocket(fd, false);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
close(fd);
|
||||||
|
delete newSocket;
|
||||||
|
delete *addr;
|
||||||
|
*addr = NULL;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
// initialize socket
|
// initialize socket
|
||||||
newSocket->m_fd = fd;
|
newSocket->m_fd = fd;
|
||||||
newSocket->m_connected = true;
|
|
||||||
newSocket->m_refCount = 1;
|
newSocket->m_refCount = 1;
|
||||||
|
|
||||||
// discard address if not requested
|
// discard address if not requested
|
||||||
|
@ -221,32 +222,22 @@ CArchNetworkBSD::acceptSocket(CArchSocket s, CArchNetAddress* addr)
|
||||||
return newSocket;
|
return newSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CArchNetworkBSD::connectSocket(CArchSocket s, CArchNetAddress addr)
|
CArchNetworkBSD::connectSocket(CArchSocket s, CArchNetAddress addr)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
assert(addr != NULL);
|
assert(addr != NULL);
|
||||||
|
|
||||||
do {
|
|
||||||
if (connect(s->m_fd, &addr->m_addr, addr->m_len) == -1) {
|
if (connect(s->m_fd, &addr->m_addr, addr->m_len) == -1) {
|
||||||
if (errno == EINTR) {
|
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno == EISCONN) {
|
if (errno == EISCONN) {
|
||||||
// already connected
|
return true;
|
||||||
break;
|
}
|
||||||
|
if (errno == EINPROGRESS) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
} while (false);
|
return true;
|
||||||
|
|
||||||
ARCH->lockMutex(m_mutex);
|
|
||||||
s->m_connected = true;
|
|
||||||
ARCH->unlockMutex(m_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_POLL
|
#if HAVE_POLL
|
||||||
|
@ -435,23 +426,13 @@ CArchNetworkBSD::readSocket(CArchSocket s, void* buf, size_t len)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
|
|
||||||
ssize_t n;
|
ssize_t n = read(s->m_fd, buf, len);
|
||||||
do {
|
|
||||||
n = read(s->m_fd, buf, len);
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
// interrupted system call
|
return 0;
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (errno == EAGAIN) {
|
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,24 +441,13 @@ CArchNetworkBSD::writeSocket(CArchSocket s, const void* buf, size_t len)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
|
|
||||||
ssize_t n;
|
ssize_t n = write(s->m_fd, buf, len);
|
||||||
do {
|
|
||||||
n = write(s->m_fd, buf, len);
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
// interrupted system call
|
return 0;
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (errno == EAGAIN) {
|
|
||||||
// no buffer space
|
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,26 +469,24 @@ CArchNetworkBSD::throwErrorOnSocket(CArchSocket s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
CArchNetworkBSD::setBlockingOnSocket(CArchSocket s, bool blocking)
|
CArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(fd != -1);
|
||||||
|
|
||||||
int mode = fcntl(s->m_fd, F_GETFL, 0);
|
int mode = fcntl(fd, F_GETFL, 0);
|
||||||
if (mode == -1) {
|
if (mode == -1) {
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
bool old = ((mode & O_NDELAY) == 0);
|
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
mode &= ~O_NDELAY;
|
mode &= ~O_NDELAY;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mode |= O_NDELAY;
|
mode |= O_NDELAY;
|
||||||
}
|
}
|
||||||
if (fcntl(s->m_fd, F_SETFL, mode) == -1) {
|
if (fcntl(fd, F_SETFL, mode) == -1) {
|
||||||
throwError(errno);
|
throwError(errno);
|
||||||
}
|
}
|
||||||
return old;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -775,8 +743,9 @@ void
|
||||||
CArchNetworkBSD::throwError(int err)
|
CArchNetworkBSD::throwError(int err)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case EAGAIN:
|
case EINTR:
|
||||||
throw XArchNetworkWouldBlock(new XArchEvalUnix(err));
|
ARCH->testCancelThread();
|
||||||
|
throw XArchNetworkInterrupted(new XArchEvalUnix(err));
|
||||||
|
|
||||||
case EACCES:
|
case EACCES:
|
||||||
case EPERM:
|
case EPERM:
|
||||||
|
@ -833,10 +802,6 @@ CArchNetworkBSD::throwError(int err)
|
||||||
case ECONNREFUSED:
|
case ECONNREFUSED:
|
||||||
throw XArchNetworkConnectionRefused(new XArchEvalUnix(err));
|
throw XArchNetworkConnectionRefused(new XArchEvalUnix(err));
|
||||||
|
|
||||||
case EINPROGRESS:
|
|
||||||
case EALREADY:
|
|
||||||
throw XArchNetworkConnecting(new XArchEvalUnix(err));
|
|
||||||
|
|
||||||
case EHOSTDOWN:
|
case EHOSTDOWN:
|
||||||
case ETIMEDOUT:
|
case ETIMEDOUT:
|
||||||
throw XArchNetworkTimedOut(new XArchEvalUnix(err));
|
throw XArchNetworkTimedOut(new XArchEvalUnix(err));
|
||||||
|
|
|
@ -30,7 +30,6 @@ typedef int socklen_t;
|
||||||
class CArchSocketImpl {
|
class CArchSocketImpl {
|
||||||
public:
|
public:
|
||||||
int m_fd;
|
int m_fd;
|
||||||
bool m_connected;
|
|
||||||
int m_refCount;
|
int m_refCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,14 +57,13 @@ public:
|
||||||
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
||||||
virtual void listenOnSocket(CArchSocket s);
|
virtual void listenOnSocket(CArchSocket s);
|
||||||
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
||||||
virtual void connectSocket(CArchSocket s, CArchNetAddress name);
|
virtual bool connectSocket(CArchSocket s, CArchNetAddress name);
|
||||||
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
||||||
virtual void unblockPollSocket(CArchThread thread);
|
virtual void unblockPollSocket(CArchThread thread);
|
||||||
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
||||||
virtual size_t writeSocket(CArchSocket s,
|
virtual size_t writeSocket(CArchSocket s,
|
||||||
const void* buf, size_t len);
|
const void* buf, size_t len);
|
||||||
virtual void throwErrorOnSocket(CArchSocket);
|
virtual void throwErrorOnSocket(CArchSocket);
|
||||||
virtual bool setBlockingOnSocket(CArchSocket, bool blocking);
|
|
||||||
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
||||||
virtual std::string getHostName();
|
virtual std::string getHostName();
|
||||||
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
||||||
|
@ -81,6 +79,7 @@ public:
|
||||||
virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress);
|
virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setBlockingOnSocket(int fd, bool blocking);
|
||||||
void throwError(int);
|
void throwError(int);
|
||||||
void throwNameError(int);
|
void throwNameError(int);
|
||||||
|
|
||||||
|
|
|
@ -187,17 +187,22 @@ CArchNetworkWinsock::init(HMODULE module)
|
||||||
CArchSocket
|
CArchSocket
|
||||||
CArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type)
|
CArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type)
|
||||||
{
|
{
|
||||||
// allocate socket object
|
|
||||||
CArchSocketImpl* socket = new CArchSocketImpl;
|
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
SOCKET fd = socket_winsock(s_family[family], s_type[type], 0);
|
SOCKET fd = socket_winsock(s_family[family], s_type[type], 0);
|
||||||
if (fd == INVALID_SOCKET) {
|
if (fd == INVALID_SOCKET) {
|
||||||
throwError(getsockerror_winsock());
|
throwError(getsockerror_winsock());
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
setBlockingOnSocket(fd, false);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
close(fd);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate socket object
|
||||||
|
CArchSocketImpl* socket = new CArchSocketImpl;
|
||||||
socket->m_socket = fd;
|
socket->m_socket = fd;
|
||||||
socket->m_connected = false;
|
|
||||||
socket->m_refCount = 1;
|
socket->m_refCount = 1;
|
||||||
socket->m_event = WSACreateEvent_winsock();
|
socket->m_event = WSACreateEvent_winsock();
|
||||||
socket->m_pollWrite = false;
|
socket->m_pollWrite = false;
|
||||||
|
@ -228,23 +233,14 @@ CArchNetworkWinsock::closeSocket(CArchSocket s)
|
||||||
|
|
||||||
// close the socket if necessary
|
// close the socket if necessary
|
||||||
if (doClose) {
|
if (doClose) {
|
||||||
do {
|
|
||||||
if (close_winsock(s->m_socket) == SOCKET_ERROR) {
|
if (close_winsock(s->m_socket) == SOCKET_ERROR) {
|
||||||
// close failed
|
// close failed. restore the last ref and throw.
|
||||||
int err = getsockerror_winsock();
|
int err = getsockerror_winsock();
|
||||||
if (err == WSAEINTR) {
|
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the last ref and throw
|
|
||||||
ARCH->lockMutex(m_mutex);
|
ARCH->lockMutex(m_mutex);
|
||||||
++s->m_refCount;
|
++s->m_refCount;
|
||||||
ARCH->unlockMutex(m_mutex);
|
ARCH->unlockMutex(m_mutex);
|
||||||
throwError(err);
|
throwError(err);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
WSACloseEvent_winsock(s->m_event);
|
WSACloseEvent_winsock(s->m_event);
|
||||||
delete s;
|
delete s;
|
||||||
}
|
}
|
||||||
|
@ -306,26 +302,31 @@ CArchNetworkWinsock::acceptSocket(CArchSocket s, CArchNetAddress* addr)
|
||||||
CArchNetAddress tmp = CArchNetAddressImpl::alloc(sizeof(struct sockaddr));
|
CArchNetAddress tmp = CArchNetAddressImpl::alloc(sizeof(struct sockaddr));
|
||||||
|
|
||||||
// accept on socket
|
// accept on socket
|
||||||
SOCKET fd;
|
SOCKET fd = accept_winsock(s->m_socket, &tmp->m_addr, &tmp->m_len);
|
||||||
do {
|
|
||||||
fd = accept_winsock(s->m_socket, &tmp->m_addr, &tmp->m_len);
|
|
||||||
if (fd == INVALID_SOCKET) {
|
if (fd == INVALID_SOCKET) {
|
||||||
int err = getsockerror_winsock();
|
int err = getsockerror_winsock();
|
||||||
delete socket;
|
delete socket;
|
||||||
free(tmp);
|
free(tmp);
|
||||||
*addr = NULL;
|
*addr = NULL;
|
||||||
if (err == WSAEINTR) {
|
if (err == WSAEWOULDBLOCK) {
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
throwError(err);
|
throwError(err);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
|
try {
|
||||||
|
setBlockingOnSocket(fd, false);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
close(fd);
|
||||||
|
delete socket;
|
||||||
|
free(tmp);
|
||||||
|
*addr = NULL;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
// initialize socket
|
// initialize socket
|
||||||
socket->m_socket = fd;
|
socket->m_socket = fd;
|
||||||
socket->m_connected = true;
|
|
||||||
socket->m_refCount = 1;
|
socket->m_refCount = 1;
|
||||||
socket->m_event = WSACreateEvent_winsock();
|
socket->m_event = WSACreateEvent_winsock();
|
||||||
socket->m_pollWrite = true;
|
socket->m_pollWrite = true;
|
||||||
|
@ -339,39 +340,23 @@ CArchNetworkWinsock::acceptSocket(CArchSocket s, CArchNetAddress* addr)
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CArchNetworkWinsock::connectSocket(CArchSocket s, CArchNetAddress addr)
|
CArchNetworkWinsock::connectSocket(CArchSocket s, CArchNetAddress addr)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
assert(addr != NULL);
|
assert(addr != NULL);
|
||||||
|
|
||||||
do {
|
|
||||||
if (connect_winsock(s->m_socket, &addr->m_addr,
|
if (connect_winsock(s->m_socket, &addr->m_addr,
|
||||||
addr->m_len) == SOCKET_ERROR) {
|
addr->m_len) == SOCKET_ERROR) {
|
||||||
if (getsockerror_winsock() == WSAEINTR) {
|
|
||||||
// interrupted system call
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getsockerror_winsock() == WSAEISCONN) {
|
if (getsockerror_winsock() == WSAEISCONN) {
|
||||||
// already connected
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getsockerror_winsock() == WSAEWOULDBLOCK) {
|
if (getsockerror_winsock() == WSAEWOULDBLOCK) {
|
||||||
// connecting
|
return false;
|
||||||
throw XArchNetworkConnecting(new XArchEvalWinsock(
|
|
||||||
getsockerror_winsock()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throwError(getsockerror_winsock());
|
throwError(getsockerror_winsock());
|
||||||
}
|
}
|
||||||
} while (false);
|
return true;
|
||||||
|
|
||||||
ARCH->lockMutex(m_mutex);
|
|
||||||
s->m_connected = true;
|
|
||||||
ARCH->unlockMutex(m_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -540,23 +525,14 @@ CArchNetworkWinsock::readSocket(CArchSocket s, void* buf, size_t len)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
|
|
||||||
int n;
|
int n = recv_winsock(s->m_socket, buf, len, 0);
|
||||||
do {
|
|
||||||
n = recv_winsock(s->m_socket, buf, len, 0);
|
|
||||||
if (n == SOCKET_ERROR) {
|
if (n == SOCKET_ERROR) {
|
||||||
if (getsockerror_winsock() == WSAEINTR) {
|
int err = getsockerror_winsock();
|
||||||
// interrupted system call
|
if (err == WSAEINTR || err == WSAEWOULDBLOCK) {
|
||||||
n = 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (getsockerror_winsock() == WSAEWOULDBLOCK) {
|
throwError(err);
|
||||||
n = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
throwError(getsockerror_winsock());
|
|
||||||
}
|
|
||||||
} while (false);
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
return static_cast<size_t>(n);
|
return static_cast<size_t>(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,24 +541,18 @@ CArchNetworkWinsock::writeSocket(CArchSocket s, const void* buf, size_t len)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
|
|
||||||
int n;
|
int n = send_winsock(s->m_socket, buf, len, 0);
|
||||||
do {
|
|
||||||
n = send_winsock(s->m_socket, buf, len, 0);
|
|
||||||
if (n == SOCKET_ERROR) {
|
if (n == SOCKET_ERROR) {
|
||||||
if (getsockerror_winsock() == WSAEINTR) {
|
int err = getsockerror_winsock();
|
||||||
// interrupted system call
|
if (err == WSAEINTR) {
|
||||||
n = 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (getsockerror_winsock() == WSAEWOULDBLOCK) {
|
if (err == WSAEWOULDBLOCK) {
|
||||||
s->m_pollWrite = true;
|
s->m_pollWrite = true;
|
||||||
n = 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
throwError(getsockerror_winsock());
|
throwError(err);
|
||||||
}
|
}
|
||||||
} while (false);
|
|
||||||
ARCH->testCancelThread();
|
|
||||||
return static_cast<size_t>(n);
|
return static_cast<size_t>(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,17 +575,15 @@ CArchNetworkWinsock::throwErrorOnSocket(CArchSocket s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
CArchNetworkWinsock::setBlockingOnSocket(CArchSocket s, bool blocking)
|
CArchNetworkWinsock::setBlockingOnSocket(SOCKET s, bool blocking)
|
||||||
{
|
{
|
||||||
assert(s != NULL);
|
assert(s != NULL);
|
||||||
|
|
||||||
int flag = blocking ? 0 : 1;
|
int flag = blocking ? 0 : 1;
|
||||||
if (ioctl_winsock(s->m_socket, FIONBIO, &flag) == SOCKET_ERROR) {
|
if (ioctl_winsock(s, FIONBIO, &flag) == SOCKET_ERROR) {
|
||||||
throwError(getsockerror_winsock());
|
throwError(getsockerror_winsock());
|
||||||
}
|
}
|
||||||
// FIXME -- can't get the current blocking state of socket?
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -841,9 +809,6 @@ void
|
||||||
CArchNetworkWinsock::throwError(int err)
|
CArchNetworkWinsock::throwError(int err)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case WSAEWOULDBLOCK:
|
|
||||||
throw XArchNetworkWouldBlock(new XArchEvalWinsock(err));
|
|
||||||
|
|
||||||
case WSAEACCES:
|
case WSAEACCES:
|
||||||
throw XArchNetworkAccess(new XArchEvalWinsock(err));
|
throw XArchNetworkAccess(new XArchEvalWinsock(err));
|
||||||
|
|
||||||
|
@ -890,10 +855,6 @@ CArchNetworkWinsock::throwError(int err)
|
||||||
case WSAECONNREFUSED:
|
case WSAECONNREFUSED:
|
||||||
throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
|
throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
|
||||||
|
|
||||||
case WSAEINPROGRESS:
|
|
||||||
case WSAEALREADY:
|
|
||||||
throw XArchNetworkConnecting(new XArchEvalWinsock(err));
|
|
||||||
|
|
||||||
case WSAEHOSTDOWN:
|
case WSAEHOSTDOWN:
|
||||||
case WSAETIMEDOUT:
|
case WSAETIMEDOUT:
|
||||||
throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
|
throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
class CArchSocketImpl {
|
class CArchSocketImpl {
|
||||||
public:
|
public:
|
||||||
SOCKET m_socket;
|
SOCKET m_socket;
|
||||||
bool m_connected;
|
|
||||||
int m_refCount;
|
int m_refCount;
|
||||||
WSAEVENT m_event;
|
WSAEVENT m_event;
|
||||||
bool m_pollWrite;
|
bool m_pollWrite;
|
||||||
|
@ -63,14 +62,13 @@ public:
|
||||||
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
virtual void bindSocket(CArchSocket s, CArchNetAddress addr);
|
||||||
virtual void listenOnSocket(CArchSocket s);
|
virtual void listenOnSocket(CArchSocket s);
|
||||||
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr);
|
||||||
virtual void connectSocket(CArchSocket s, CArchNetAddress name);
|
virtual bool connectSocket(CArchSocket s, CArchNetAddress name);
|
||||||
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
virtual int pollSocket(CPollEntry[], int num, double timeout);
|
||||||
virtual void unblockPollSocket(CArchThread thread);
|
virtual void unblockPollSocket(CArchThread thread);
|
||||||
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
virtual size_t readSocket(CArchSocket s, void* buf, size_t len);
|
||||||
virtual size_t writeSocket(CArchSocket s,
|
virtual size_t writeSocket(CArchSocket s,
|
||||||
const void* buf, size_t len);
|
const void* buf, size_t len);
|
||||||
virtual void throwErrorOnSocket(CArchSocket);
|
virtual void throwErrorOnSocket(CArchSocket);
|
||||||
virtual bool setBlockingOnSocket(CArchSocket, bool blocking);
|
|
||||||
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay);
|
||||||
virtual std::string getHostName();
|
virtual std::string getHostName();
|
||||||
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
virtual CArchNetAddress newAnyAddr(EAddressFamily);
|
||||||
|
@ -88,6 +86,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void init(HMODULE);
|
void init(HMODULE);
|
||||||
|
|
||||||
|
void setBlockingOnSocket(SOCKET, bool blocking);
|
||||||
|
|
||||||
void throwError(int);
|
void throwError(int);
|
||||||
void throwNameError(int);
|
void throwNameError(int);
|
||||||
|
|
||||||
|
|
|
@ -152,25 +152,21 @@ public:
|
||||||
end. \c addr may be NULL if the remote address isn't required.
|
end. \c addr may be NULL if the remote address isn't required.
|
||||||
The original socket \c s is unaffected and remains in the listening
|
The original socket \c s is unaffected and remains in the listening
|
||||||
state. The new socket shares most of the properties of \c s except
|
state. The new socket shares most of the properties of \c s except
|
||||||
it's not in the listening state, it's connected, and is not
|
it's not in the listening state and it's connected. Returns NULL
|
||||||
non-blocking even is \c s is.
|
if there are no pending connection requests.
|
||||||
|
|
||||||
This call blocks if \c s is not non-blocking and there are no
|
|
||||||
pending connection requests.
|
|
||||||
|
|
||||||
(Cancellation point)
|
|
||||||
*/
|
*/
|
||||||
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr) = 0;
|
virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr) = 0;
|
||||||
|
|
||||||
//! Connect socket
|
//! Connect socket
|
||||||
/*!
|
/*!
|
||||||
Connects the socket \c s to the remote address \c addr. This call
|
Connects the socket \c s to the remote address \c addr. Returns
|
||||||
blocks if \c s is not non-blocking. If \c s is non-blocking then
|
true if the connection succeed immediately, false if the connection
|
||||||
the client can \c poll() for writability to detect a connection.
|
is in progress, and throws if the connection failed immediately.
|
||||||
|
If it returns false, \c pollSocket() can be used to wait on the
|
||||||
(Cancellation point)
|
socket for writing to detect when the connection finally succeeds
|
||||||
|
or fails.
|
||||||
*/
|
*/
|
||||||
virtual void connectSocket(CArchSocket s, CArchNetAddress addr) = 0;
|
virtual bool connectSocket(CArchSocket s, CArchNetAddress addr) = 0;
|
||||||
|
|
||||||
//! Check socket state
|
//! Check socket state
|
||||||
/*!
|
/*!
|
||||||
|
@ -202,12 +198,7 @@ public:
|
||||||
Read up to \c len bytes from socket \c s in \c buf and return the
|
Read up to \c len bytes from socket \c s in \c buf and return the
|
||||||
number of bytes read. The number of bytes can be less than \c len
|
number of bytes read. The number of bytes can be less than \c len
|
||||||
if not enough data is available. Returns 0 if the remote end has
|
if not enough data is available. Returns 0 if the remote end has
|
||||||
disconnected and there is no more queued received data. Blocks if
|
disconnected and/or there is no more queued received data.
|
||||||
the socket is not non-blocking and there is no queued received data.
|
|
||||||
If non-blocking and there is no queued received data then throws
|
|
||||||
XArchNetworkWouldBlock.
|
|
||||||
|
|
||||||
(Cancellation point)
|
|
||||||
*/
|
*/
|
||||||
virtual size_t readSocket(CArchSocket s, void* buf, size_t len) = 0;
|
virtual size_t readSocket(CArchSocket s, void* buf, size_t len) = 0;
|
||||||
|
|
||||||
|
@ -215,12 +206,8 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Write up to \c len bytes to socket \c s from \c buf and return the
|
Write up to \c len bytes to socket \c s from \c buf and return the
|
||||||
number of bytes written. The number of bytes can be less than
|
number of bytes written. The number of bytes can be less than
|
||||||
\c len if the remote end disconnected or the socket is non-blocking
|
\c len if the remote end disconnected or the internal buffers fill
|
||||||
and the internal buffers are full. If non-blocking and the internal
|
up.
|
||||||
buffers are full before any data is written then throws
|
|
||||||
XArchNetworkWouldBlock.
|
|
||||||
|
|
||||||
(Cancellation point)
|
|
||||||
*/
|
*/
|
||||||
virtual size_t writeSocket(CArchSocket s,
|
virtual size_t writeSocket(CArchSocket s,
|
||||||
const void* buf, size_t len) = 0;
|
const void* buf, size_t len) = 0;
|
||||||
|
@ -232,14 +219,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void throwErrorOnSocket(CArchSocket s) = 0;
|
virtual void throwErrorOnSocket(CArchSocket s) = 0;
|
||||||
|
|
||||||
//! Set socket to (non-)blocking operation
|
|
||||||
/*!
|
|
||||||
Set socket to block or not block on accept, connect, poll, read and
|
|
||||||
write (i.e. calls that may take an arbitrary amount of time).
|
|
||||||
Returns the previous state.
|
|
||||||
*/
|
|
||||||
virtual bool setBlockingOnSocket(CArchSocket, bool blocking) = 0;
|
|
||||||
|
|
||||||
//! Turn Nagle algorithm on or off on socket
|
//! Turn Nagle algorithm on or off on socket
|
||||||
/*!
|
/*!
|
||||||
Set socket to send messages immediately (true) or to collect small
|
Set socket to send messages immediately (true) or to collect small
|
||||||
|
|
|
@ -90,8 +90,8 @@ library to indicate various errors.
|
||||||
*/
|
*/
|
||||||
XARCH_SUBCLASS(XArchNetwork, XArch);
|
XARCH_SUBCLASS(XArchNetwork, XArch);
|
||||||
|
|
||||||
//! Operation would block
|
//! Operation was interrupted
|
||||||
XARCH_SUBCLASS(XArchNetworkWouldBlock, XArchNetwork);
|
XARCH_SUBCLASS(XArchNetworkInterrupted, XArchNetwork);
|
||||||
|
|
||||||
//! Network insufficient permission
|
//! Network insufficient permission
|
||||||
XARCH_SUBCLASS(XArchNetworkAccess, XArchNetwork);
|
XARCH_SUBCLASS(XArchNetworkAccess, XArchNetwork);
|
||||||
|
@ -126,9 +126,6 @@ XARCH_SUBCLASS(XArchNetworkDisconnected, XArchNetwork);
|
||||||
//! Remote end of socket refused connection
|
//! Remote end of socket refused connection
|
||||||
XARCH_SUBCLASS(XArchNetworkConnectionRefused, XArchNetwork);
|
XARCH_SUBCLASS(XArchNetworkConnectionRefused, XArchNetwork);
|
||||||
|
|
||||||
//! Connection is in progress
|
|
||||||
XARCH_SUBCLASS(XArchNetworkConnecting, XArchNetwork);
|
|
||||||
|
|
||||||
//! Remote end of socket is not responding
|
//! Remote end of socket is not responding
|
||||||
XARCH_SUBCLASS(XArchNetworkTimedOut, XArchNetwork);
|
XARCH_SUBCLASS(XArchNetworkTimedOut, XArchNetwork);
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ CTCPListenSocket::bind(const CNetworkAddress& addr)
|
||||||
CLock lock(m_mutex);
|
CLock lock(m_mutex);
|
||||||
ARCH->bindSocket(m_socket, addr.getAddress());
|
ARCH->bindSocket(m_socket, addr.getAddress());
|
||||||
ARCH->listenOnSocket(m_socket);
|
ARCH->listenOnSocket(m_socket);
|
||||||
ARCH->setBlockingOnSocket(m_socket, false);
|
|
||||||
CSocketMultiplexer::getInstance()->addSocket(this,
|
CSocketMultiplexer::getInstance()->addSocket(this,
|
||||||
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
||||||
this, &CTCPListenSocket::serviceListening,
|
this, &CTCPListenSocket::serviceListening,
|
||||||
|
@ -104,10 +103,12 @@ CTCPListenSocket::accept()
|
||||||
try {
|
try {
|
||||||
IDataSocket* socket =
|
IDataSocket* socket =
|
||||||
new CTCPSocket(ARCH->acceptSocket(m_socket, NULL));
|
new CTCPSocket(ARCH->acceptSocket(m_socket, NULL));
|
||||||
|
if (socket != NULL) {
|
||||||
CSocketMultiplexer::getInstance()->addSocket(this,
|
CSocketMultiplexer::getInstance()->addSocket(this,
|
||||||
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
||||||
this, &CTCPListenSocket::serviceListening,
|
this, &CTCPListenSocket::serviceListening,
|
||||||
m_socket, true, false));
|
m_socket, true, false));
|
||||||
|
}
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
catch (XArchNetwork&) {
|
catch (XArchNetwork&) {
|
||||||
|
|
|
@ -275,14 +275,15 @@ CTCPSocket::connect(const CNetworkAddress& addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ARCH->connectSocket(m_socket, addr.getAddress());
|
if (ARCH->connectSocket(m_socket, addr.getAddress())) {
|
||||||
sendSocketEvent(getConnectedEvent());
|
sendSocketEvent(getConnectedEvent());
|
||||||
onConnected();
|
onConnected();
|
||||||
}
|
}
|
||||||
catch (XArchNetworkConnecting&) {
|
else {
|
||||||
// connection is in progress
|
// connection is in progress
|
||||||
m_writable = true;
|
m_writable = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (XArchNetwork& e) {
|
catch (XArchNetwork& e) {
|
||||||
throw XSocketConnect(e.what());
|
throw XSocketConnect(e.what());
|
||||||
}
|
}
|
||||||
|
@ -299,9 +300,6 @@ CTCPSocket::init()
|
||||||
m_writable = false;
|
m_writable = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// make socket non-blocking
|
|
||||||
ARCH->setBlockingOnSocket(m_socket, false);
|
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
Loading…
Reference in New Issue