fcntl patch for UNIX platforms; code compiled and tests run on Mac & Win

This commit is contained in:
Aleksandar Fabijanic 2012-04-26 02:57:16 +00:00
parent 15d960b057
commit a9cef39021
3 changed files with 47 additions and 9 deletions

View File

@ -148,6 +148,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#if POCO_OS != POCO_OS_HPUX
#include <sys/select.h>
#endif
@ -170,6 +171,7 @@
#define POCO_INVALID_SOCKET -1
#define poco_socket_t int
#define poco_socklen_t socklen_t
#define poco_fcntl_request_t int
#if defined(POCO_OS_FAMILY_BSD)
#define poco_ioctl_request_t unsigned long
#else

View File

@ -352,8 +352,6 @@ public:
virtual bool getBlocking() const;
/// Returns the blocking mode of the socket.
/// This method will only work if the blocking modes of
/// the socket are changed via the setBlocking method!
virtual bool secure() const;
/// Returns true iff the socket's connection is secure
@ -372,6 +370,14 @@ public:
void ioctl(poco_ioctl_request_t request, void* arg);
/// A wrapper for the ioctl system call.
#if defined(POCO_OS_FAMILY_UNIX)
int fcntl(poco_fcntl_request_t request);
/// A wrapper for the fcntl system call.
int fcntl(poco_fcntl_request_t request, long arg);
/// A wrapper for the fcntl system call.
#endif
bool initialized() const;
/// Returns true iff the underlying socket is initialized.

View File

@ -293,7 +293,7 @@ int SocketImpl::sendBytes(const void* buffer, int length, int flags)
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags);
}
while (rc < 0 && lastError() == POCO_EINTR);
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
}
@ -315,11 +315,13 @@ int SocketImpl::receiveBytes(void* buffer, int length, int flags)
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags);
}
while (rc < 0 && lastError() == POCO_EINTR);
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0)
{
int err = lastError();
if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT)
if (err == POCO_EAGAIN && !_blocking)
;
else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT)
throw TimeoutException();
else
error(err);
@ -340,7 +342,7 @@ int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& addr
rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length());
#endif
}
while (rc < 0 && lastError() == POCO_EINTR);
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
}
@ -365,7 +367,7 @@ int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, in
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen);
}
while (rc < 0 && lastError() == POCO_EINTR);
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc >= 0)
{
address = SocketAddress(pSA, saLen);
@ -373,7 +375,9 @@ int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, in
else
{
int err = lastError();
if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT)
if (err == POCO_EAGAIN && !_blocking)
;
else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT)
throw TimeoutException();
else
error(err);
@ -851,9 +855,17 @@ bool SocketImpl::getBroadcast()
void SocketImpl::setBlocking(bool flag)
{
#if !defined(POCO_OS_FAMILY_UNIX)
int arg = flag ? 0 : 1;
ioctl(FIONBIO, arg);
_blocking = flag;
#else
int arg = fcntl(F_GETFL);
long flags = arg & ~O_NONBLOCK;
if (!flag)
flags |= O_NONBLOCK;
(void) fcntl(F_SETFL, flags);
#endif
_blocking = flag;
}
@ -907,6 +919,24 @@ void SocketImpl::ioctl(poco_ioctl_request_t request, void* arg)
}
#if defined(POCO_OS_FAMILY_UNIX)
int SocketImpl::fcntl(poco_fcntl_request_t request)
{
int rc = ::fcntl(_sockfd, request);
if (rc == -1) error();
return rc;
}
int SocketImpl::fcntl(poco_fcntl_request_t request, long arg)
{
int rc = ::fcntl(_sockfd, request, arg);
if (rc == -1) error();
return rc;
}
#endif
void SocketImpl::reset(poco_socket_t aSocket)
{
_sockfd = aSocket;