Made all arch sockets non-blocking.

This commit is contained in:
crs 2004-02-29 16:11:17 +00:00
parent 75cafe65a6
commit d6ec331b09
10 changed files with 179 additions and 286 deletions

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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));

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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&) {

View File

@ -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.