summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp')
-rw-r--r--tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp1269
1 files changed, 0 insertions, 1269 deletions
diff --git a/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp b/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp
deleted file mode 100644
index 46c3932..0000000
--- a/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp
+++ /dev/null
@@ -1,1269 +0,0 @@
-/****************************************************************************
-**
-** Implementation of TQSocketDevice class.
-**
-** Created : 970521
-**
-** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA.
-**
-** This file is part of the network module of the TQt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free TQt Foundation.
-**
-** Please review the following information to ensure GNU General
-** Public Licensing requirements will be met:
-** http://trolltech.com/products/qt/licenses/licensing/opensource/.
-** If you are unsure which license is appropriate for your use, please
-** review the following information:
-** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
-** or contact the sales department at sales@trolltech.com.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
-** included in the packaging of this file. Licensees holding valid TQt
-** Commercial licenses may use this file in accordance with the TQt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
-
-#include "tqplatformdefs.h"
-
-// Almost always the same. If not, specify in qplatformdefs.h.
-#if !defined(TQT_SOCKOPTLEN_T)
-# define TQT_SOCKOPTLEN_T TQT_SOCKLEN_T
-#endif
-
-// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
-static inline int qt_socket_accept(int s, struct sockaddr *addr, TQT_SOCKLEN_T *addrlen)
-{ return ::accept(s, addr, addrlen); }
-#if defined(accept)
-# undef accept
-#endif
-
-// Solaris redefines bind -> __xnet_bind with _XOPEN_SOURCE_EXTENDED
-static inline int qt_socket_bind(int s, struct sockaddr *addr, TQT_SOCKLEN_T addrlen)
-{ return ::bind(s, addr, addrlen); }
-#if defined(bind)
-# undef bind
-#endif
-
-// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED
-static inline int qt_socket_connect(int s, struct sockaddr *addr, TQT_SOCKLEN_T addrlen)
-{ return ::connect(s, addr, addrlen); }
-#if defined(connect)
-# undef connect
-#endif
-
-// UnixWare 7 redefines listen -> _listen
-static inline int qt_socket_listen(int s, int backlog)
-{ return ::listen(s, backlog); }
-#if defined(listen)
-# undef listen
-#endif
-
-// UnixWare 7 redefines socket -> _socket
-static inline int qt_socket_socket(int domain, int type, int protocol)
-{ return ::socket(domain, type, protocol); }
-#if defined(socket)
-# undef socket
-#endif
-
-#include "tqsocketdevice.h"
-
-#ifndef TQT_NO_NETWORK
-
-#include "tqwindowdefs.h"
-
-#include <errno.h>
-#include <sys/types.h>
-
-
-static inline void qt_socket_getportaddr( struct sockaddr *sa,
- TQ_UINT16 *port, TQHostAddress *addr )
-{
-#if !defined(TQT_NO_IPV6)
- if ( sa->sa_family == AF_INET6 ) {
- struct sockaddr_in6 *sa6 = ( struct sockaddr_in6 * )sa;
- TQ_IPV6ADDR tmp;
- memcpy( &tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp) );
- TQHostAddress a( tmp );
- *addr = a;
- *port = ntohs( sa6->sin6_port );
- return;
- }
-#endif
- struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
- TQHostAddress a( ntohl( sa4->sin_addr.s_addr ) );
- *port = ntohs( sa4->sin_port );
- *addr = TQHostAddress( ntohl( sa4->sin_addr.s_addr ) );
- return;
-}
-
-#ifdef USE_QT4
-
-qint64 TQSocketDevice::readData( char *data, qint64 maxlen )
-{
-#if defined(QT_CHECK_NULL)
- if ( data == 0 && maxlen != 0 ) {
- qWarning( "TQSocketDevice::readBlock: Null pointer error" );
- }
-#endif
-#if defined(QT_CHECK_STATE)
- if ( !isValid() ) {
- qWarning( "TQSocketDevice::readBlock: Invalid socket" );
- return -1;
- }
- if ( !isOpen() ) {
- qWarning( "TQSocketDevice::readBlock: Device is not open" );
- return -1;
- }
- if ( !isReadable() ) {
- qWarning( "TQSocketDevice::readBlock: Read operation not permitted" );
- return -1;
- }
-#endif
- bool done = false;
- int r = 0;
- while ( done == false ) {
- if ( t == Datagram ) {
-#if !defined(QT_NO_IPV6)
- struct sockaddr_storage aa;
-#else
- struct sockaddr_in aa;
-#endif
- memset( &aa, 0, sizeof(aa) );
- QT_SOCKLEN_T sz;
- sz = sizeof( aa );
- r = ::recvfrom( fd, data, maxlen, 0,
- (struct sockaddr *)&aa, &sz );
-
- qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa);
-
- } else {
- r = ::read( fd, data, maxlen );
- }
- done = true;
- if ( r == 0 && t == Stream && maxlen > 0 ) {
- // connection closed
- close();
- } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) {
- // nothing
- } else if ( errno == EINTR ) {
- done = false;
- } else if ( e == NoError ) {
- switch( errno ) {
- case EIO:
- case EISDIR:
- case EBADF:
- case EINVAL:
- case EFAULT:
- case ENOTCONN:
- case ENOTSOCK:
- e = Impossible;
- break;
-#if defined(ENONET)
- case ENONET:
-#endif
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- e = NetworkFailure;
- break;
- case EPIPE:
- case ECONNRESET:
- // connection closed
- close();
- r = 0;
- break;
- default:
- e = UnknownError;
- break;
- }
- }
- }
- return r;
-}
-
-
-qint64 TQSocketDevice::writeData( const char *data, qint64 len )
-{
- if ( data == 0 && len != 0 ) {
-#if defined(QT_CHECK_NULL) || defined(QSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Null pointer error" );
-#endif
- return -1;
- }
- if ( !isValid() ) {
-#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Invalid socket" );
-#endif
- return -1;
- }
- if ( !isOpen() ) {
-#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Device is not open" );
-#endif
- return -1;
- }
- if ( !isWritable() ) {
-#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Write operation not permitted" );
-#endif
- return -1;
- }
- bool done = false;
- int r = 0;
- bool timeout;
- while ( !done ) {
- r = ::write( fd, data, len );
- done = true;
- if ( r < 0 && e == NoError &&
- errno != EAGAIN && errno != EWOULDBLOCK ) {
- switch( errno ) {
- case EINTR: // signal - call read() or whatever again
- done = false;
- break;
- case EPIPE:
- case ECONNRESET:
- // connection closed
- close();
- r = 0;
- break;
- case ENOSPC:
- case EIO:
- case EISDIR:
- case EBADF:
- case EINVAL:
- case EFAULT:
- case ENOTCONN:
- case ENOTSOCK:
- e = Impossible;
- break;
-#if defined(ENONET)
- case ENONET:
-#endif
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- e = NetworkFailure;
- break;
- default:
- e = UnknownError;
- break;
- }
- } else if ( waitForMore( 0, &timeout ) == 0 ) {
- if ( !timeout ) {
- // connection closed
- close();
- }
- }
- }
- return r;
-}
-
-#endif // USE_QT4
-
-
-//#define TQSOCKETDEVICE_DEBUG
-
-// internal
-void TQSocketDevice::init()
-{
-}
-
-
-TQSocketDevice::Protocol TQSocketDevice::getProtocol() const
-{
- if ( isValid() ) {
-#if !defined (TQT_NO_IPV6)
- struct sockaddr_storage sa;
-#else
- struct sockaddr sa;
-#endif
- memset( &sa, 0, sizeof(sa) );
- TQT_SOCKLEN_T sz = sizeof( sa );
-#if !defined (TQT_NO_IPV6)
- struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
- if ( !::getsockname(fd, sap, &sz) ) {
- switch ( sap->sa_family ) {
- case AF_INET:
- return IPv4;
- case AF_INET6:
- return IPv6;
- default:
- return Unknown;
- }
- }
-#else
- if ( !::getsockname(fd, &sa, &sz) ) {
- switch ( sa.sa_family ) {
- case AF_INET:
- return IPv4;
- default:
- return Unknown;
- }
- }
-#endif
- }
- return Unknown;
-}
-
-/*!
- Creates a new socket identifier. Returns -1 if there is a failure
- to create the new identifier; error() explains why.
-
- \sa setSocket()
-*/
-
-int TQSocketDevice::createNewSocket()
-{
-#if !defined(TQT_NO_IPV6)
- int s = qt_socket_socket( protocol() == IPv6 ? AF_INET6 : AF_INET,
- t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0 );
-#else
- int s = qt_socket_socket( AF_INET, t==Datagram?SOCK_DGRAM:SOCK_STREAM, 0 );
-#endif
- if ( s < 0 ) {
- switch( errno ) {
- case EPROTONOSUPPORT:
- e = InternalError; // 0 is supposed to work for both types
- break;
- case ENFILE:
- e = NoFiles; // special case for this
- break;
- case EACCES:
- e = Inaccessible;
- break;
- case ENOBUFS:
- case ENOMEM:
- e = NoResources;
- break;
- case EINVAL:
- e = Impossible;
- break;
- default:
- e = UnknownError;
- break;
- }
- } else {
- // ensure that the socket is closed on exec..() after being dup()'ed by
- // fork() in TQProcess.
- ::fcntl(s, F_SETFD, FD_CLOEXEC);
- return s;
- }
- return -1;
-}
-
-/*!
- \reimp
-
- Closes the socket and sets the socket identifier to -1 (invalid).
-
- (This function ignores errors; if there are any then a file
- descriptor leakage might result. As far as we know, the only error
- that can arise is EBADF, and that would of course not cause
- leakage. There may be OS-specfic errors that we haven't come
- across, however.)
-
- \sa open()
-*/
-void TQSocketDevice::close()
-{
- if ( fd == -1 || !isOpen() ) // already closed
- return;
- setFlags( IO_Sequential );
- resetqStatus();
- setState( 0 );
- ::close( fd );
-#if defined(TQSOCKETDEVICE_DEBUG)
- qDebug( "TQSocketDevice::close: Closed socket %x", fd );
-#endif
- fd = -1;
- fetchConnectionParameters();
-}
-
-
-/*!
- Returns TRUE if the socket is valid and in blocking mode;
- otherwise returns FALSE.
-
- Note that this function does not set error().
-
- \warning On Windows, this function always returns TRUE since the
- ioctlsocket() function is broken.
-
- \sa setBlocking(), isValid()
-*/
-bool TQSocketDevice::blocking() const
-{
- if ( !isValid() )
- return TRUE;
- int s = fcntl(fd, F_GETFL, 0);
- return !(s >= 0 && ((s & O_NDELAY) != 0));
-}
-
-
-/*!
- Makes the socket blocking if \a enable is TRUE or nonblocking if
- \a enable is FALSE.
-
- Sockets are blocking by default, but we recommend using
- nonblocking socket operations, especially for GUI programs that
- need to be responsive.
-
- \warning On Windows, this function should be used with care since
- whenever you use a TQSocketNotifier on Windows, the socket is
- immediately made nonblocking.
-
- \sa blocking(), isValid()
-*/
-void TQSocketDevice::setBlocking( bool enable )
-{
-#if defined(TQSOCKETDEVICE_DEBUG)
- qDebug( "TQSocketDevice::setBlocking( %d )", enable );
-#endif
- if ( !isValid() )
- return;
- int tmp = ::fcntl(fd, F_GETFL, 0);
- if ( tmp >= 0 )
- tmp = ::fcntl( fd, F_SETFL, enable ? (tmp&~O_NDELAY) : (tmp|O_NDELAY) );
- if ( tmp >= 0 )
- return;
- if ( e )
- return;
- switch( errno ) {
- case EACCES:
- case EBADF:
- e = Impossible;
- break;
- case EFAULT:
- case EAGAIN:
-#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
-#endif
- case EDEADLK:
- case EINTR:
- case EINVAL:
- case EMFILE:
- case ENOLCK:
- case EPERM:
- default:
- e = UnknownError;
- }
-}
-
-
-/*!
- Returns the value of the socket option \a opt.
-*/
-int TQSocketDevice::option( Option opt ) const
-{
- if ( !isValid() )
- return -1;
- int n = -1;
- int v = -1;
- switch ( opt ) {
- case Broadcast:
- n = SO_BROADCAST;
- break;
- case ReceiveBuffer:
- n = SO_RCVBUF;
- break;
- case ReuseAddress:
- n = SO_REUSEADDR;
- break;
- case SendBuffer:
- n = SO_SNDBUF;
- break;
- }
- if ( n != -1 ) {
- TQT_SOCKOPTLEN_T len;
- len = sizeof(v);
- int r = ::getsockopt( fd, SOL_SOCKET, n, (char*)&v, &len );
- if ( r >= 0 )
- return v;
- if ( !e ) {
- TQSocketDevice *that = (TQSocketDevice*)this; // mutable function
- switch( errno ) {
- case EBADF:
- case ENOTSOCK:
- that->e = Impossible;
- break;
- case EFAULT:
- that->e = InternalError;
- break;
- default:
- that->e = UnknownError;
- break;
- }
- }
- return -1;
- }
- return v;
-}
-
-
-/*!
- Sets the socket option \a opt to \a v.
-*/
-void TQSocketDevice::setOption( Option opt, int v )
-{
- if ( !isValid() )
- return;
- int n = -1; // for really, really bad compilers
- switch ( opt ) {
- case Broadcast:
- n = SO_BROADCAST;
- break;
- case ReceiveBuffer:
- n = SO_RCVBUF;
- break;
- case ReuseAddress:
- n = SO_REUSEADDR;
- break;
- case SendBuffer:
- n = SO_SNDBUF;
- break;
- default:
- return;
- }
- if ( ::setsockopt( fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
- e == NoError ) {
- switch( errno ) {
- case EBADF:
- case ENOTSOCK:
- e = Impossible;
- break;
- case EFAULT:
- e = InternalError;
- break;
- default:
- e = UnknownError;
- break;
- }
- }
-}
-
-
-/*!
- Connects to the IP address and port specified by \a addr and \a
- port. Returns TRUE if it establishes a connection; otherwise returns FALSE.
- If it returns FALSE, error() explains why.
-
- Note that error() commonly returns NoError for non-blocking
- sockets; this just means that you can call connect() again in a
- little while and it'll probably succeed.
-*/
-bool TQSocketDevice::connect( const TQHostAddress &addr, TQ_UINT16 port )
-{
- if ( !isValid() )
- return FALSE;
-
- pa = addr;
- pp = port;
-
- struct sockaddr_in a4;
- struct sockaddr *aa;
- TQT_SOCKLEN_T aalen;
-
-#if !defined(TQT_NO_IPV6)
- struct sockaddr_in6 a6;
-
- if ( addr.isIPv6Address() ) {
- memset( &a6, 0, sizeof(a6) );
- a6.sin6_family = AF_INET6;
- a6.sin6_port = htons( port );
- TQ_IPV6ADDR ip6 = addr.toIPv6Address();
- memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) );
-
- aalen = sizeof( a6 );
- aa = (struct sockaddr *)&a6;
- } else
-#endif
- if ( addr.isIPv4Address() ) {
- memset( &a4, 0, sizeof(a4) );
- a4.sin_family = AF_INET;
- a4.sin_port = htons( port );
- a4.sin_addr.s_addr = htonl( addr.toIPv4Address() );
-
- aalen = sizeof(a4);
- aa = (struct sockaddr *)&a4;
- } else {
- e = Impossible;
- return FALSE;
- }
-
- int r = qt_socket_connect( fd, aa, aalen );
- if ( r == 0 ) {
- fetchConnectionParameters();
- return TRUE;
- }
- if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) {
- fetchConnectionParameters();
- return TRUE;
- }
- if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) {
- return FALSE;
- }
- switch( errno ) {
- case EBADF:
- case ENOTSOCK:
- e = Impossible;
- break;
- case EFAULT:
- case EAFNOSUPPORT:
- e = InternalError;
- break;
- case ECONNREFUSED:
- e = ConnectionRefused;
- break;
- case ETIMEDOUT:
- case ENETUNREACH:
- e = NetworkFailure;
- break;
- case EADDRINUSE:
- e = NoResources;
- break;
- case EACCES:
- case EPERM:
- e = Inaccessible;
- break;
- default:
- e = UnknownError;
- break;
- }
- return FALSE;
-}
-
-
-/*!
- Assigns a name to an unnamed socket. The name is the host address
- \a address and the port number \a port. If the operation succeeds,
- bind() returns TRUE; otherwise it returns FALSE without changing
- what port() and address() return.
-
- bind() is used by servers for setting up incoming connections.
- Call bind() before listen().
-*/
-bool TQSocketDevice::bind( const TQHostAddress &address, TQ_UINT16 port )
-{
- if ( !isValid() )
- return FALSE;
- int r;
- struct sockaddr_in a4;
-#if !defined(TQT_NO_IPV6)
- struct sockaddr_in6 a6;
-
- if ( address.isIPv6Address() ) {
- memset( &a6, 0, sizeof(a6) );
- a6.sin6_family = AF_INET6;
- a6.sin6_port = htons( port );
- TQ_IPV6ADDR tmp = address.toIPv6Address();
- memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) );
-
- r = qt_socket_bind( fd, (struct sockaddr *)&a6, sizeof(a6) );
- } else
-#endif
- if ( address.isIPv4Address() ) {
- memset( &a4, 0, sizeof(a4) );
- a4.sin_family = AF_INET;
- a4.sin_port = htons( port );
- a4.sin_addr.s_addr = htonl( address.toIPv4Address() );
-
- r = qt_socket_bind( fd, (struct sockaddr*)&a4, sizeof(a4) );
- } else {
- e = Impossible;
- return FALSE;
- }
-
- if ( r < 0 ) {
- switch( errno ) {
- case EINVAL:
- e = AlreadyBound;
- break;
- case EACCES:
- e = Inaccessible;
- break;
- case ENOMEM:
- e = NoResources;
- break;
- case EFAULT: // a was illegal
- case ENAMETOOLONG: // sz was wrong
- e = InternalError;
- break;
- case EBADF: // AF_UNIX only
- case ENOTSOCK: // AF_UNIX only
- case EROFS: // AF_UNIX only
- case ENOENT: // AF_UNIX only
- case ENOTDIR: // AF_UNIX only
- case ELOOP: // AF_UNIX only
- e = Impossible;
- break;
- default:
- e = UnknownError;
- break;
- }
- return FALSE;
- }
- fetchConnectionParameters();
- return TRUE;
-}
-
-
-/*!
- Specifies how many pending connections a server socket can have.
- Returns TRUE if the operation was successful; otherwise returns
- FALSE. A \a backlog value of 50 is quite common.
-
- The listen() call only applies to sockets where type() is \c
- Stream, i.e. not to \c Datagram sockets. listen() must not be
- called before bind() or after accept().
-
- \sa bind(), accept()
-*/
-bool TQSocketDevice::listen( int backlog )
-{
- if ( !isValid() )
- return FALSE;
- if ( qt_socket_listen( fd, backlog ) >= 0 )
- return TRUE;
- if ( !e )
- e = Impossible;
- return FALSE;
-}
-
-
-/*!
- Extracts the first connection from the queue of pending
- connections for this socket and returns a new socket identifier.
- Returns -1 if the operation failed.
-
- \sa bind(), listen()
-*/
-int TQSocketDevice::accept()
-{
- if ( !isValid() )
- return -1;
-
-#if !defined (TQT_NO_IPV6)
- struct sockaddr_storage aa;
-#else
- struct sockaddr aa;
-#endif
- TQT_SOCKLEN_T l = sizeof( aa );
- bool done;
- int s;
- do {
- s = qt_socket_accept( fd, (struct sockaddr*)&aa, &l );
- // we'll blithely throw away the stuff accept() wrote to aa
- done = TRUE;
- if ( s < 0 && e == NoError ) {
- switch( errno ) {
- case EINTR:
- done = FALSE;
- break;
-#if defined(EPROTO)
- case EPROTO:
-#endif
-#if defined(ENONET)
- case ENONET:
-#endif
- case ENOPROTOOPT:
- case EHOSTDOWN:
- case EOPNOTSUPP:
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- // in all these cases, an error happened during connection
- // setup. we're not interested in what happened, so we
- // just treat it like the client-closed-quickly case.
- case EPERM:
- // firewalling wouldn't let us accept. we treat it like
- // the client-closed-quickly case.
- case EAGAIN:
-#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
-#endif
- // the client closed the connection before we got around
- // to accept()ing it.
- break;
- case EBADF:
- case ENOTSOCK:
- e = Impossible;
- break;
- case EFAULT:
- e = InternalError;
- break;
- case ENOMEM:
- case ENOBUFS:
- e = NoResources;
- break;
- default:
- e = UnknownError;
- break;
- }
- }
- } while (!done);
- // ensure that the socket is closed on exec..() after being dup()'ed by
- // fork() in TQProcess.
- ::fcntl(s, F_SETFD, FD_CLOEXEC);
- return s;
-}
-
-
-/*!
- Returns the number of bytes available for reading, or -1 if an
- error occurred.
-
- \warning On Microsoft Windows, we use the ioctlsocket() function
- to determine the number of bytes queued on the socket. According
- to Microsoft (KB Q125486), ioctlsocket() sometimes returns an
- incorrect number. The only safe way to determine the amount of
- data on the socket is to read it using readBlock(). TQSocket has
- workarounds to deal with this problem.
-*/
-#ifdef USE_QT4
-qint64 TQSocketDevice::bytesAvailable() const
-#else // USE_QT4
-TQ_LONG TQSocketDevice::bytesAvailable() const
-#endif // USE_QT4
-{
- if ( !isValid() )
- return -1;
-
- /*
- Apparently, there is not consistency among different operating
- systems on how to use FIONREAD.
-
- FreeBSD, Linux and Solaris all expect the 3rd argument to
- ioctl() to be an int, which is normally 32-bit even on 64-bit
- machines.
-
- IRIX, on the other hand, expects a size_t, which is 64-bit on
- 64-bit machines.
-
- So, the solution is to use size_t initialized to zero to make
- sure all bits are set to zero, preventing underflow with the
- FreeBSD/Linux/Solaris ioctls.
- */
- size_t nbytes = 0;
- // gives shorter than true amounts on Unix domain sockets.
- if ( ::ioctl(fd, FIONREAD, (char*)&nbytes) < 0 )
- return -1;
- return (TQ_LONG) *((int *) &nbytes);
-}
-
-
-/*!
- Wait up to \a msecs milliseconds for more data to be available. If
- \a msecs is -1 the call will block indefinitely.
-
- Returns the number of bytes available for reading, or -1 if an
- error occurred.
-
- If \a timeout is non-null and no error occurred (i.e. it does not
- return -1): this function sets \a *timeout to TRUE, if the reason
- for returning was that the timeout was reached; otherwise it sets
- \a *timeout to FALSE. This is useful to find out if the peer
- closed the connection.
-
- \warning This is a blocking call and should be avoided in event
- driven applications.
-
- \sa bytesAvailable()
-*/
-TQ_LONG TQSocketDevice::waitForMore( int msecs, bool *timeout ) const
-{
- if ( !isValid() )
- return -1;
- if ( fd >= FD_SETSIZE )
- return -1;
-
- fd_set fds;
- struct timeval tv;
-
- FD_ZERO( &fds );
- FD_SET( fd, &fds );
-
- tv.tv_sec = msecs / 1000;
- tv.tv_usec = (msecs % 1000) * 1000;
-
- int rv = select( fd+1, &fds, 0, 0, msecs < 0 ? 0 : &tv );
-
- if ( rv < 0 )
- return -1;
-
- if ( timeout ) {
- if ( rv == 0 )
- *timeout = TRUE;
- else
- *timeout = FALSE;
- }
-
- return bytesAvailable();
-}
-
-
-/*!
- Reads \a maxlen bytes from the socket into \a data and returns the
- number of bytes read. Returns -1 if an error occurred. Returning 0
- is not an error. For Stream sockets, 0 is returned when the remote
- host closes the connection. For Datagram sockets, 0 is a valid
- datagram size.
-*/
-TQ_LONG TQSocketDevice::readBlock( char *data, TQ_ULONG maxlen )
-{
-#if defined(TQT_CHECK_NULL)
- if ( data == 0 && maxlen != 0 ) {
- qWarning( "TQSocketDevice::readBlock: Null pointer error" );
- }
-#endif
-#if defined(TQT_CHECK_STATE)
- if ( !isValid() ) {
- qWarning( "TQSocketDevice::readBlock: Invalid socket" );
- return -1;
- }
- if ( !isOpen() ) {
- qWarning( "TQSocketDevice::readBlock: Device is not open" );
- return -1;
- }
- if ( !isReadable() ) {
- qWarning( "TQSocketDevice::readBlock: Read operation not permitted" );
- return -1;
- }
-#endif
- bool done = FALSE;
- int r = 0;
- while ( done == FALSE ) {
- if ( t == Datagram ) {
-#if !defined(TQT_NO_IPV6)
- struct sockaddr_storage aa;
-#else
- struct sockaddr_in aa;
-#endif
- memset( &aa, 0, sizeof(aa) );
- TQT_SOCKLEN_T sz;
- sz = sizeof( aa );
- r = ::recvfrom( fd, data, maxlen, 0,
- (struct sockaddr *)&aa, &sz );
-
- qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa);
-
- } else {
- r = ::read( fd, data, maxlen );
- }
- done = TRUE;
- if ( r == 0 && t == Stream && maxlen > 0 ) {
- // connection closed
- close();
- } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) {
- // nothing
- } else if ( errno == EINTR ) {
- done = FALSE;
- } else if ( e == NoError ) {
- switch( errno ) {
- case EIO:
- case EISDIR:
- case EBADF:
- case EINVAL:
- case EFAULT:
- case ENOTCONN:
- case ENOTSOCK:
- e = Impossible;
- break;
-#if defined(ENONET)
- case ENONET:
-#endif
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- e = NetworkFailure;
- break;
- case EPIPE:
- case ECONNRESET:
- // connection closed
- close();
- r = 0;
- break;
- default:
- e = UnknownError;
- break;
- }
- }
- }
- return r;
-}
-
-
-/*!
- Writes \a len bytes to the socket from \a data and returns the
- number of bytes written. Returns -1 if an error occurred.
-
- This is used for \c TQSocketDevice::Stream sockets.
-*/
-TQ_LONG TQSocketDevice::writeBlock( const char *data, TQ_ULONG len )
-{
- if ( data == 0 && len != 0 ) {
-#if defined(TQT_CHECK_NULL) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Null pointer error" );
-#endif
- return -1;
- }
- if ( !isValid() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Invalid socket" );
-#endif
- return -1;
- }
- if ( !isOpen() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Device is not open" );
-#endif
- return -1;
- }
- if ( !isWritable() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::writeBlock: Write operation not permitted" );
-#endif
- return -1;
- }
- bool done = FALSE;
- int r = 0;
- bool timeout;
- while ( !done ) {
- r = ::write( fd, data, len );
- done = TRUE;
- if ( r < 0 && e == NoError &&
- errno != EAGAIN && errno != EWOULDBLOCK ) {
- switch( errno ) {
- case EINTR: // signal - call read() or whatever again
- done = FALSE;
- break;
- case EPIPE:
- case ECONNRESET:
- // connection closed
- close();
- r = 0;
- break;
- case ENOSPC:
- case EIO:
- case EISDIR:
- case EBADF:
- case EINVAL:
- case EFAULT:
- case ENOTCONN:
- case ENOTSOCK:
- e = Impossible;
- break;
-#if defined(ENONET)
- case ENONET:
-#endif
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- e = NetworkFailure;
- break;
- default:
- e = UnknownError;
- break;
- }
- } else if ( waitForMore( 0, &timeout ) == 0 ) {
- if ( !timeout ) {
- // connection closed
- close();
- }
- }
- }
- return r;
-}
-
-
-/*!
- \overload
-
- Writes \a len bytes to the socket from \a data and returns the
- number of bytes written. Returns -1 if an error occurred.
-
- This is used for \c TQSocketDevice::Datagram sockets. You must
- specify the \a host and \a port of the destination of the data.
-*/
-TQ_LONG TQSocketDevice::writeBlock( const char * data, TQ_ULONG len,
- const TQHostAddress & host, TQ_UINT16 port )
-{
- if ( t != Datagram ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::sendBlock: Not datagram" );
-#endif
- return -1; // for now - later we can do t/tcp
- }
-
- if ( data == 0 && len != 0 ) {
-#if defined(TQT_CHECK_NULL) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::sendBlock: Null pointer error" );
-#endif
- return -1;
- }
- if ( !isValid() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::sendBlock: Invalid socket" );
-#endif
- return -1;
- }
- if ( !isOpen() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::sendBlock: Device is not open" );
-#endif
- return -1;
- }
- if ( !isWritable() ) {
-#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG)
- qWarning( "TQSocketDevice::sendBlock: Write operation not permitted" );
-#endif
- return -1;
- }
- struct sockaddr_in a4;
- struct sockaddr *aa;
- TQT_SOCKLEN_T slen;
-#if !defined(TQT_NO_IPV6)
- struct sockaddr_in6 a6;
- if ( host.isIPv6Address() ) {
- memset( &a6, 0, sizeof(a6) );
- a6.sin6_family = AF_INET6;
- a6.sin6_port = htons( port );
-
- TQ_IPV6ADDR tmp = host.toIPv6Address();
- memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) );
- slen = sizeof( a6 );
- aa = (struct sockaddr *)&a6;
- } else
-#endif
- if ( host.isIPv4Address() ) {
- memset( &a4, 0, sizeof(a4) );
- a4.sin_family = AF_INET;
- a4.sin_port = htons( port );
- a4.sin_addr.s_addr = htonl( host.toIPv4Address() );
- slen = sizeof(a4);
- aa = (struct sockaddr *)&a4;
- } else {
- e = Impossible;
- return -1;
- }
-
- // we'd use MSG_DONTWAIT + MSG_NOTQT_SIGNAL if Stevens were right.
- // but apparently Stevens and most implementors disagree
- bool done = FALSE;
- int r = 0;
- while ( !done ) {
- r = ::sendto( fd, data, len, 0, aa, slen);
- done = TRUE;
- if ( r < 0 && e == NoError &&
- errno != EAGAIN && errno != EWOULDBLOCK ) {
- switch( errno ) {
- case EINTR: // signal - call read() or whatever again
- done = FALSE;
- break;
- case ENOSPC:
- case EPIPE:
- case EIO:
- case EISDIR:
- case EBADF:
- case EINVAL:
- case EFAULT:
- case ENOTCONN:
- case ENOTSOCK:
- e = Impossible;
- break;
-#if defined(ENONET)
- case ENONET:
-#endif
- case EHOSTUNREACH:
- case ENETDOWN:
- case ENETUNREACH:
- case ETIMEDOUT:
- e = NetworkFailure;
- break;
- default:
- e = UnknownError;
- break;
- }
- }
- }
- return r;
-}
-
-
-/*!
- Fetches information about both ends of the connection: whatever is
- available.
-*/
-void TQSocketDevice::fetchConnectionParameters()
-{
- if ( !isValid() ) {
- p = 0;
- a = TQHostAddress();
- pp = 0;
- pa = TQHostAddress();
- return;
- }
-#if !defined(TQT_NO_IPV6)
- struct sockaddr_storage sa;
-#else
- struct sockaddr_in sa;
-#endif
- memset( &sa, 0, sizeof(sa) );
- TQT_SOCKLEN_T sz;
- sz = sizeof( sa );
- if ( !::getsockname( fd, (struct sockaddr *)(&sa), &sz ) )
- qt_socket_getportaddr( (struct sockaddr *)&sa, &p, &a );
-
- sz = sizeof( sa );
- if ( !::getpeername( fd, (struct sockaddr *)(&sa), &sz ) )
- qt_socket_getportaddr( (struct sockaddr *)&sa, &pp, &pa );
-}
-
-
-/*!
- Returns the port number of the port this socket tqdevice is
- connected to. This may be 0 for a while, but is set to something
- sensible as soon as a sensible value is available.
-
- Note that for Datagram sockets, this is the source port of the
- last packet received, and that it is in native byte order.
-*/
-TQ_UINT16 TQSocketDevice::peerPort() const
-{
- return pp;
-}
-
-
-/*!
- Returns the address of the port this socket tqdevice is connected
- to. This may be 0.0.0.0 for a while, but is set to something
- sensible as soon as a sensible value is available.
-
- Note that for Datagram sockets, this is the source port of the
- last packet received.
-*/
-TQHostAddress TQSocketDevice::peerAddress() const
-{
- return pa;
-}
-
-#endif //TQT_NO_NETWORK