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

View File

@@ -352,8 +352,6 @@ public:
virtual bool getBlocking() const; virtual bool getBlocking() const;
/// Returns the blocking mode of the socket. /// 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; virtual bool secure() const;
/// Returns true iff the socket's connection is secure /// Returns true iff the socket's connection is secure
@@ -372,6 +370,14 @@ public:
void ioctl(poco_ioctl_request_t request, void* arg); void ioctl(poco_ioctl_request_t request, void* arg);
/// A wrapper for the ioctl system call. /// 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; bool initialized() const;
/// Returns true iff the underlying socket is initialized. /// 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(); if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags); 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(); if (rc < 0) error();
return rc; return rc;
} }
@@ -315,11 +315,13 @@ int SocketImpl::receiveBytes(void* buffer, int length, int flags)
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags); 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) if (rc < 0)
{ {
int err = lastError(); 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(); throw TimeoutException();
else else
error(err); 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()); rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length());
#endif #endif
} }
while (rc < 0 && lastError() == POCO_EINTR); while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error(); if (rc < 0) error();
return rc; return rc;
} }
@@ -365,7 +367,7 @@ int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, in
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen); 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) if (rc >= 0)
{ {
address = SocketAddress(pSA, saLen); address = SocketAddress(pSA, saLen);
@@ -373,7 +375,9 @@ int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, in
else else
{ {
int err = lastError(); 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(); throw TimeoutException();
else else
error(err); error(err);
@@ -851,9 +855,17 @@ bool SocketImpl::getBroadcast()
void SocketImpl::setBlocking(bool flag) void SocketImpl::setBlocking(bool flag)
{ {
#if !defined(POCO_OS_FAMILY_UNIX)
int arg = flag ? 0 : 1; int arg = flag ? 0 : 1;
ioctl(FIONBIO, arg); 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) void SocketImpl::reset(poco_socket_t aSocket)
{ {
_sockfd = aSocket; _sockfd = aSocket;