src/network/socket/qnativesocketengine_unix.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 //#define QNATIVESOCKETENGINE_DEBUG
       
    43 #include "qnativesocketengine_p.h"
       
    44 #include "private/qnet_unix_p.h"
       
    45 #include "qiodevice.h"
       
    46 #include "qhostaddress.h"
       
    47 #include "qvarlengtharray.h"
       
    48 #include "qdatetime.h"
       
    49 #include <time.h>
       
    50 #include <errno.h>
       
    51 #include <fcntl.h>
       
    52 #ifndef QT_NO_IPV6IFNAME
       
    53 #include <net/if.h>
       
    54 #endif
       
    55 #ifndef QT_NO_IPV6IFNAME
       
    56 #include <net/if.h>
       
    57 #endif
       
    58 #ifdef QT_LINUXBASE
       
    59 #include <arpa/inet.h>
       
    60 #endif
       
    61 
       
    62 #if defined QNATIVESOCKETENGINE_DEBUG
       
    63 #include <qstring.h>
       
    64 #include <ctype.h>
       
    65 #endif
       
    66 
       
    67 #ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right?
       
    68 #include <sys/socket.h>
       
    69 #include <netinet/in.h>
       
    70 #else
       
    71 #include <netinet/tcp.h>
       
    72 #endif
       
    73 
       
    74 QT_BEGIN_NAMESPACE
       
    75 
       
    76 #if defined QNATIVESOCKETENGINE_DEBUG
       
    77 
       
    78 /*
       
    79     Returns a human readable representation of the first \a len
       
    80     characters in \a data.
       
    81 */
       
    82 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
       
    83 {
       
    84     if (!data) return "(null)";
       
    85     QByteArray out;
       
    86     for (int i = 0; i < len; ++i) {
       
    87         char c = data[i];
       
    88         if (isprint(c)) {
       
    89             out += c;
       
    90         } else switch (c) {
       
    91         case '\n': out += "\\n"; break;
       
    92         case '\r': out += "\\r"; break;
       
    93         case '\t': out += "\\t"; break;
       
    94         default:
       
    95             QString tmp;
       
    96             tmp.sprintf("\\%o", c);
       
    97             out += tmp.toLatin1();
       
    98         }
       
    99     }
       
   100 
       
   101     if (len < maxSize)
       
   102         out += "...";
       
   103 
       
   104     return out;
       
   105 }
       
   106 #endif
       
   107 
       
   108 static void qt_ignore_sigpipe()
       
   109 {
       
   110 #ifndef Q_NO_POSIX_SIGNALS
       
   111     // Set to ignore SIGPIPE once only.
       
   112     static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
       
   113     if (atom.testAndSetRelaxed(0, 1)) {
       
   114         struct sigaction noaction;
       
   115         memset(&noaction, 0, sizeof(noaction));
       
   116         noaction.sa_handler = SIG_IGN;
       
   117         ::sigaction(SIGPIPE, &noaction, 0);
       
   118     }
       
   119 #else
       
   120     // Posix signals are not supported by the underlying platform
       
   121     // so we don't need to ignore sigpipe signal explicitly
       
   122 #endif
       
   123 }
       
   124 
       
   125 /*
       
   126     Extracts the port and address from a sockaddr, and stores them in
       
   127     \a port and \a addr if they are non-null.
       
   128 */
       
   129 static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr)
       
   130 {
       
   131 #if !defined(QT_NO_IPV6)
       
   132     if (s->a.sa_family == AF_INET6) {
       
   133         Q_IPV6ADDR tmp;
       
   134         memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp));
       
   135         if (addr) {
       
   136             QHostAddress tmpAddress;
       
   137             tmpAddress.setAddress(tmp);
       
   138             *addr = tmpAddress;
       
   139 #ifndef QT_NO_IPV6IFNAME
       
   140             char scopeid[IFNAMSIZ];
       
   141             if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
       
   142                 addr->setScopeId(QLatin1String(scopeid));
       
   143             } else
       
   144 #endif
       
   145             addr->setScopeId(QString::number(s->a6.sin6_scope_id));
       
   146         }
       
   147         if (port)
       
   148             *port = ntohs(s->a6.sin6_port);
       
   149         return;
       
   150     }
       
   151 #endif
       
   152     if (port)
       
   153         *port = ntohs(s->a4.sin_port);
       
   154     if (addr) {
       
   155         QHostAddress tmpAddress;
       
   156         tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr));
       
   157         *addr = tmpAddress;
       
   158     }
       
   159 }
       
   160 
       
   161 /*! \internal
       
   162 
       
   163     Creates and returns a new socket descriptor of type \a socketType
       
   164     and \a socketProtocol.  Returns -1 on failure.
       
   165 */
       
   166 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType,
       
   167                                          QAbstractSocket::NetworkLayerProtocol socketProtocol)
       
   168 {
       
   169 #ifndef QT_NO_IPV6
       
   170     int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
       
   171 #else
       
   172     Q_UNUSED(socketProtocol);
       
   173     int protocol = AF_INET;
       
   174 #endif
       
   175     int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
       
   176 #ifdef Q_OS_SYMBIAN
       
   177     int socket = ::socket(protocol, type, 0);
       
   178 #else
       
   179 	int socket = qt_safe_socket(protocol, type, 0);
       
   180 #endif
       
   181 
       
   182     if (socket <= 0) {
       
   183         switch (errno) {
       
   184         case EPROTONOSUPPORT:
       
   185         case EAFNOSUPPORT:
       
   186         case EINVAL:
       
   187             setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
       
   188             break;
       
   189         case ENFILE:
       
   190         case EMFILE:
       
   191         case ENOBUFS:
       
   192         case ENOMEM:
       
   193             setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
       
   194             break;
       
   195         case EACCES:
       
   196             setError(QAbstractSocket::SocketAccessError, AccessErrorString);
       
   197             break;
       
   198         default:
       
   199             break;
       
   200         }
       
   201 
       
   202         return false;
       
   203     }
       
   204 
       
   205     // Ensure that the socket is closed on exec*().
       
   206     ::fcntl(socket, F_SETFD, FD_CLOEXEC);
       
   207 
       
   208     socketDescriptor = socket;
       
   209     return true;
       
   210 }
       
   211 
       
   212 /*
       
   213     Returns the value of the socket option \a opt.
       
   214 */
       
   215 int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
       
   216 {
       
   217     Q_Q(const QNativeSocketEngine);
       
   218     if (!q->isValid())
       
   219         return -1;
       
   220 
       
   221     int n = -1;
       
   222     int level = SOL_SOCKET; // default
       
   223 
       
   224     switch (opt) {
       
   225     case QNativeSocketEngine::ReceiveBufferSocketOption:
       
   226         n = SO_RCVBUF;
       
   227         break;
       
   228     case QNativeSocketEngine::SendBufferSocketOption:
       
   229         n = SO_SNDBUF;
       
   230         break;
       
   231     case QNativeSocketEngine::NonBlockingSocketOption:
       
   232         break;
       
   233     case QNativeSocketEngine::BroadcastSocketOption:
       
   234         break;
       
   235     case QNativeSocketEngine::AddressReusable:
       
   236         n = SO_REUSEADDR;
       
   237         break;
       
   238     case QNativeSocketEngine::BindExclusively:
       
   239         return true;
       
   240     case QNativeSocketEngine::ReceiveOutOfBandData:
       
   241         n = SO_OOBINLINE;
       
   242         break;
       
   243     case QNativeSocketEngine::LowDelayOption:
       
   244         level = IPPROTO_TCP;
       
   245         n = TCP_NODELAY;
       
   246         break;
       
   247     case QNativeSocketEngine::KeepAliveOption:
       
   248         n = SO_KEEPALIVE;
       
   249         break;
       
   250     }
       
   251 
       
   252     int v = -1;
       
   253     QT_SOCKOPTLEN_T len = sizeof(v);
       
   254     if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
       
   255         return v;
       
   256 
       
   257     return -1;
       
   258 }
       
   259 
       
   260 
       
   261 /*
       
   262     Sets the socket option \a opt to \a v.
       
   263 */
       
   264 bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
       
   265 {
       
   266     Q_Q(QNativeSocketEngine);
       
   267     if (!q->isValid())
       
   268         return false;
       
   269 
       
   270     int n = 0;
       
   271     int level = SOL_SOCKET; // default
       
   272 
       
   273     switch (opt) {
       
   274     case QNativeSocketEngine::ReceiveBufferSocketOption:
       
   275         n = SO_RCVBUF;
       
   276         break;
       
   277     case QNativeSocketEngine::SendBufferSocketOption:
       
   278         n = SO_SNDBUF;
       
   279         break;
       
   280     case QNativeSocketEngine::BroadcastSocketOption:
       
   281         n = SO_BROADCAST;
       
   282         break;
       
   283     case QNativeSocketEngine::NonBlockingSocketOption: {
       
   284         // Make the socket nonblocking.
       
   285 #if !defined(Q_OS_VXWORKS)
       
   286         int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
       
   287         if (flags == -1) {
       
   288 #ifdef QNATIVESOCKETENGINE_DEBUG
       
   289             perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed");
       
   290 #endif
       
   291             return false;
       
   292         }
       
   293         if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
       
   294 #ifdef QNATIVESOCKETENGINE_DEBUG
       
   295             perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed");
       
   296 #endif
       
   297             return false;
       
   298         }
       
   299 #else // Q_OS_VXWORKS
       
   300         int onoff = 1;
       
   301 #ifdef Q_OS_SYMBIAN
       
   302         if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
       
   303 #else
       
   304         if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
       
   305 #endif
       
   306 #ifdef QNATIVESOCKETENGINE_DEBUG
       
   307             perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
       
   308 #endif
       
   309             return false;
       
   310         }
       
   311 #endif // Q_OS_VXWORKS
       
   312         return true;
       
   313     }
       
   314     case QNativeSocketEngine::AddressReusable:
       
   315 #if defined(SO_REUSEPORT) && !defined(Q_OS_SYMBIAN)
       
   316         n = SO_REUSEPORT;
       
   317 #else
       
   318         n = SO_REUSEADDR;
       
   319 #endif
       
   320         break;
       
   321     case QNativeSocketEngine::BindExclusively:
       
   322         return true;
       
   323     case QNativeSocketEngine::ReceiveOutOfBandData:
       
   324         n = SO_OOBINLINE;
       
   325         break;
       
   326     case QNativeSocketEngine::LowDelayOption:
       
   327         level = IPPROTO_TCP;
       
   328         n = TCP_NODELAY;
       
   329         break;
       
   330     case QNativeSocketEngine::KeepAliveOption:
       
   331         n = SO_KEEPALIVE;
       
   332         break;
       
   333     }
       
   334 
       
   335     return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
       
   336 }
       
   337 
       
   338 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
       
   339 {
       
   340 #ifdef QNATIVESOCKETENGINE_DEBUG
       
   341     qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
       
   342 #endif
       
   343 
       
   344     struct sockaddr_in sockAddrIPv4;
       
   345     struct sockaddr *sockAddrPtr = 0;
       
   346     QT_SOCKLEN_T sockAddrSize = 0;
       
   347 
       
   348 #if !defined(QT_NO_IPV6)
       
   349     struct sockaddr_in6 sockAddrIPv6;
       
   350 
       
   351     if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
       
   352         memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
       
   353         sockAddrIPv6.sin6_family = AF_INET6;
       
   354         sockAddrIPv6.sin6_port = htons(port);
       
   355 #ifndef QT_NO_IPV6IFNAME
       
   356         sockAddrIPv6.sin6_scope_id = ::if_nametoindex(addr.scopeId().toLatin1().data());
       
   357 #else
       
   358         sockAddrIPv6.sin6_scope_id = addr.scopeId().toInt();
       
   359 #endif
       
   360         Q_IPV6ADDR ip6 = addr.toIPv6Address();
       
   361         memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
       
   362 
       
   363         sockAddrSize = sizeof(sockAddrIPv6);
       
   364         sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
       
   365     } else
       
   366 #if 0
       
   367     {}
       
   368 #endif
       
   369 #endif
       
   370     if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
       
   371         memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
       
   372         sockAddrIPv4.sin_family = AF_INET;
       
   373         sockAddrIPv4.sin_port = htons(port);
       
   374         sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address());
       
   375 
       
   376         sockAddrSize = sizeof(sockAddrIPv4);
       
   377         sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
       
   378     } else {
       
   379         // unreachable
       
   380     }
       
   381 #ifdef Q_OS_SYMBIAN
       
   382     int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize);
       
   383 #else
       
   384     int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
       
   385 #endif
       
   386     if (connectResult == -1) {
       
   387         switch (errno) {
       
   388         case EISCONN:
       
   389             socketState = QAbstractSocket::ConnectedState;
       
   390             break;
       
   391         case ECONNREFUSED:
       
   392         case EINVAL:
       
   393             setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
       
   394             socketState = QAbstractSocket::UnconnectedState;
       
   395             break;
       
   396         case ETIMEDOUT:
       
   397             setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
       
   398             break;
       
   399         case EHOSTUNREACH:
       
   400             setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
       
   401             socketState = QAbstractSocket::UnconnectedState;
       
   402             break;
       
   403         case ENETUNREACH:
       
   404             setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
       
   405             socketState = QAbstractSocket::UnconnectedState;
       
   406             break;
       
   407         case EADDRINUSE:
       
   408             setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
       
   409             break;
       
   410         case EINPROGRESS:
       
   411         case EALREADY:
       
   412             setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
       
   413             socketState = QAbstractSocket::ConnectingState;
       
   414             break;
       
   415         case EAGAIN:
       
   416             setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
       
   417             setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
       
   418             break;
       
   419         case EACCES:
       
   420         case EPERM:
       
   421             setError(QAbstractSocket::SocketAccessError, AccessErrorString);
       
   422             socketState = QAbstractSocket::UnconnectedState;
       
   423             break;
       
   424         case EAFNOSUPPORT:
       
   425         case EBADF:
       
   426         case EFAULT:
       
   427         case ENOTSOCK:
       
   428             socketState = QAbstractSocket::UnconnectedState;
       
   429         default:
       
   430             break;
       
   431         }
       
   432 
       
   433         if (socketState != QAbstractSocket::ConnectedState) {
       
   434 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   435             qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
       
   436                    addr.toString().toLatin1().constData(), port,
       
   437                    socketState == QAbstractSocket::ConnectingState
       
   438                    ? "Connection in progress" : socketErrorString.toLatin1().constData());
       
   439 #endif
       
   440             return false;
       
   441         }
       
   442     }
       
   443 
       
   444 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   445     qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
       
   446            addr.toString().toLatin1().constData(), port);
       
   447 #endif
       
   448 
       
   449     socketState = QAbstractSocket::ConnectedState;
       
   450     return true;
       
   451 }
       
   452 
       
   453 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
       
   454 {
       
   455     struct sockaddr_in sockAddrIPv4;
       
   456     struct sockaddr *sockAddrPtr = 0;
       
   457     QT_SOCKLEN_T sockAddrSize = 0;
       
   458 
       
   459 #if !defined(QT_NO_IPV6)
       
   460     struct sockaddr_in6 sockAddrIPv6;
       
   461 
       
   462     if (address.protocol() == QAbstractSocket::IPv6Protocol) {
       
   463         memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
       
   464         sockAddrIPv6.sin6_family = AF_INET6;
       
   465         sockAddrIPv6.sin6_port = htons(port);
       
   466 #ifndef QT_NO_IPV6IFNAME
       
   467         sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data());
       
   468 #else
       
   469         sockAddrIPv6.sin6_scope_id = address.scopeId().toInt();
       
   470 #endif
       
   471         Q_IPV6ADDR tmp = address.toIPv6Address();
       
   472         memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
       
   473         sockAddrSize = sizeof(sockAddrIPv6);
       
   474         sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
       
   475     } else
       
   476 #endif
       
   477         if (address.protocol() == QAbstractSocket::IPv4Protocol) {
       
   478             memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
       
   479             sockAddrIPv4.sin_family = AF_INET;
       
   480             sockAddrIPv4.sin_port = htons(port);
       
   481             sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
       
   482             sockAddrSize = sizeof(sockAddrIPv4);
       
   483             sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
       
   484         } else {
       
   485             // unreachable
       
   486         }
       
   487 
       
   488     int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
       
   489 
       
   490     if (bindResult < 0) {
       
   491         switch(errno) {
       
   492         case EADDRINUSE:
       
   493             setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
       
   494             break;
       
   495         case EACCES:
       
   496             setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
       
   497             break;
       
   498         case EINVAL:
       
   499             setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
       
   500             break;
       
   501         case EADDRNOTAVAIL:
       
   502             setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
       
   503             break;
       
   504         default:
       
   505             break;
       
   506         }
       
   507 
       
   508 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   509         qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
       
   510                address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
       
   511 #endif
       
   512 
       
   513         return false;
       
   514     }
       
   515 
       
   516 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   517     qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
       
   518            address.toString().toLatin1().constData(), port);
       
   519 #endif
       
   520     socketState = QAbstractSocket::BoundState;
       
   521     return true;
       
   522 }
       
   523 
       
   524 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
       
   525 {
       
   526 #ifdef Q_OS_SYMBIAN
       
   527     if (::listen(socketDescriptor, backlog) < 0) {
       
   528 #else
       
   529     if (qt_safe_listen(socketDescriptor, backlog) < 0) {
       
   530 #endif
       
   531         switch (errno) {
       
   532         case EADDRINUSE:
       
   533             setError(QAbstractSocket::AddressInUseError,
       
   534                      PortInuseErrorString);
       
   535             break;
       
   536         default:
       
   537             break;
       
   538         }
       
   539 
       
   540 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   541         qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
       
   542                backlog, socketErrorString.toLatin1().constData());
       
   543 #endif
       
   544         return false;
       
   545     }
       
   546 
       
   547 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   548     qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
       
   549 #endif
       
   550 
       
   551     socketState = QAbstractSocket::ListeningState;
       
   552     return true;
       
   553 }
       
   554 
       
   555 int QNativeSocketEnginePrivate::nativeAccept()
       
   556 {
       
   557 #ifdef Q_OS_SYMBIAN
       
   558     int acceptedDescriptor = ::accept(socketDescriptor, 0, 0);
       
   559 #else
       
   560     int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
       
   561 #endif
       
   562     //check if we have vaild descriptor at all
       
   563     if(acceptedDescriptor > 0) {
       
   564         // Ensure that the socket is closed on exec*()
       
   565         ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
       
   566     }
       
   567 #ifdef Q_OS_SYMBIAN
       
   568     else {
       
   569         qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0");
       
   570     }
       
   571 #endif
       
   572 
       
   573     return acceptedDescriptor;
       
   574 }
       
   575 
       
   576 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
       
   577 {
       
   578     int nbytes = 0;
       
   579     // gives shorter than true amounts on Unix domain sockets.
       
   580     qint64 available = 0;
       
   581 #ifdef Q_OS_SYMBIAN
       
   582 	if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
       
   583 #else
       
   584     if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
       
   585 #endif
       
   586         available = (qint64) nbytes;
       
   587 
       
   588 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   589     qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available);
       
   590 #endif
       
   591     return available;
       
   592 }
       
   593 
       
   594 bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
       
   595 {
       
   596     // Create a sockaddr struct and reset its port number.
       
   597     qt_sockaddr storage;
       
   598     QT_SOCKLEN_T storageSize = sizeof(storage);
       
   599     memset(&storage, 0, storageSize);
       
   600 
       
   601     // Peek 0 bytes into the next message. The size of the message may
       
   602     // well be 0, so we can't check recvfrom's return value.
       
   603     ssize_t readBytes;
       
   604     do {
       
   605         char c;
       
   606         readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
       
   607     } while (readBytes == -1 && errno == EINTR);
       
   608 
       
   609     // If there's no error, or if our buffer was too small, there must be a
       
   610     // pending datagram.
       
   611     bool result = (readBytes != -1) || errno == EMSGSIZE;
       
   612 
       
   613 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   614     qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
       
   615            result ? "true" : "false");
       
   616 #endif
       
   617     return result;
       
   618 }
       
   619 
       
   620 #ifdef Q_OS_SYMBIAN
       
   621 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
       
   622 {
       
   623     size_t nbytes = 0;
       
   624     ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes);
       
   625     return qint64(nbytes-28);
       
   626 }
       
   627 #else
       
   628 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
       
   629 {
       
   630     QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
       
   631     ssize_t recvResult = -1;
       
   632 
       
   633     for (;;) {
       
   634         // the data written to udpMessagePeekBuffer is discarded, so
       
   635         // this function is still reentrant although it might not look
       
   636         // so.
       
   637         recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
       
   638             udpMessagePeekBuffer.size(), MSG_PEEK);
       
   639         if (recvResult == -1 && errno == EINTR)
       
   640             continue;
       
   641 
       
   642         if (recvResult != (ssize_t) udpMessagePeekBuffer.size())
       
   643             break;
       
   644 
       
   645         udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2);
       
   646     }
       
   647 
       
   648 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   649     qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %i", recvResult);
       
   650 #endif
       
   651 
       
   652     return qint64(recvResult);
       
   653 }
       
   654 #endif
       
   655 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
       
   656                                                     QHostAddress *address, quint16 *port)
       
   657 {
       
   658     qt_sockaddr aa;
       
   659     memset(&aa, 0, sizeof(aa));
       
   660     QT_SOCKLEN_T sz;
       
   661     sz = sizeof(aa);
       
   662 
       
   663     ssize_t recvFromResult = 0;
       
   664     do {
       
   665         char c;
       
   666         recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
       
   667                                     0, &aa.a, &sz);
       
   668     } while (recvFromResult == -1 && errno == EINTR);
       
   669 
       
   670     if (recvFromResult == -1) {
       
   671         setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
       
   672     } else if (port || address) {
       
   673         qt_socket_getPortAndAddress(&aa, port, address);
       
   674     }
       
   675 
       
   676 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   677     qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
       
   678            data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize,
       
   679            address ? address->toString().toLatin1().constData() : "(nil)",
       
   680            port ? *port : 0, (qint64) recvFromResult);
       
   681 #endif
       
   682 
       
   683     return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0);
       
   684 }
       
   685 
       
   686 qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
       
   687                                                    const QHostAddress &host, quint16 port)
       
   688 {
       
   689     struct sockaddr_in sockAddrIPv4;
       
   690     struct sockaddr *sockAddrPtr = 0;
       
   691     QT_SOCKLEN_T sockAddrSize = 0;
       
   692 
       
   693 #if !defined(QT_NO_IPV6)
       
   694     struct sockaddr_in6 sockAddrIPv6;
       
   695     if (host.protocol() == QAbstractSocket::IPv6Protocol) {
       
   696     memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
       
   697     sockAddrIPv6.sin6_family = AF_INET6;
       
   698     sockAddrIPv6.sin6_port = htons(port);
       
   699 
       
   700     Q_IPV6ADDR tmp = host.toIPv6Address();
       
   701     memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
       
   702     sockAddrSize = sizeof(sockAddrIPv6);
       
   703     sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
       
   704     } else
       
   705 #endif
       
   706     if (host.protocol() == QAbstractSocket::IPv4Protocol) {
       
   707     memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
       
   708     sockAddrIPv4.sin_family = AF_INET;
       
   709     sockAddrIPv4.sin_port = htons(port);
       
   710     sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
       
   711     sockAddrSize = sizeof(sockAddrIPv4);
       
   712     sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
       
   713     }
       
   714 
       
   715     // ignore the SIGPIPE signal
       
   716     qt_ignore_sigpipe();
       
   717 #ifdef Q_OS_SYMBIAN
       
   718     ssize_t sentBytes = ::sendto(socketDescriptor, data, len,
       
   719                                        0, sockAddrPtr, sockAddrSize);
       
   720 #else
       
   721     ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
       
   722                                        0, sockAddrPtr, sockAddrSize);
       
   723 #endif
       
   724 
       
   725     if (sentBytes < 0) {
       
   726         switch (errno) {
       
   727         case EMSGSIZE:
       
   728             setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
       
   729             break;
       
   730         default:
       
   731             setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
       
   732         }
       
   733     }
       
   734 
       
   735 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   736     qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
       
   737            qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(),
       
   738            port, (qint64) sentBytes);
       
   739 #endif
       
   740 
       
   741     return qint64(sentBytes);
       
   742 }
       
   743 
       
   744 bool QNativeSocketEnginePrivate::fetchConnectionParameters()
       
   745 {
       
   746     localPort = 0;
       
   747     localAddress.clear();
       
   748     peerPort = 0;
       
   749     peerAddress.clear();
       
   750 
       
   751     if (socketDescriptor == -1)
       
   752         return false;
       
   753 
       
   754     qt_sockaddr sa;
       
   755     QT_SOCKLEN_T sockAddrSize = sizeof(sa);
       
   756 
       
   757     // Determine local address
       
   758     memset(&sa, 0, sizeof(sa));
       
   759     if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
       
   760         qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
       
   761 
       
   762         // Determine protocol family
       
   763         switch (sa.a.sa_family) {
       
   764         case AF_INET:
       
   765             socketProtocol = QAbstractSocket::IPv4Protocol;
       
   766             break;
       
   767 #if !defined (QT_NO_IPV6)
       
   768         case AF_INET6:
       
   769             socketProtocol = QAbstractSocket::IPv6Protocol;
       
   770             break;
       
   771 #endif
       
   772         default:
       
   773             socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
       
   774             break;
       
   775         }
       
   776 
       
   777     } else if (errno == EBADF) {
       
   778         setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
       
   779         return false;
       
   780     }
       
   781 
       
   782     // Determine the remote address
       
   783     if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
       
   784         qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
       
   785 
       
   786     // Determine the socket type (UDP/TCP)
       
   787     int value = 0;
       
   788     QT_SOCKOPTLEN_T valueSize = sizeof(int);
       
   789     if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
       
   790         if (value == SOCK_STREAM)
       
   791             socketType = QAbstractSocket::TcpSocket;
       
   792         else if (value == SOCK_DGRAM)
       
   793             socketType = QAbstractSocket::UdpSocket;
       
   794         else
       
   795             socketType = QAbstractSocket::UnknownSocketType;
       
   796     }
       
   797 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   798     QString socketProtocolStr = "UnknownProtocol";
       
   799     if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
       
   800     else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
       
   801 
       
   802     QString socketTypeStr = "UnknownSocketType";
       
   803     if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
       
   804     else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
       
   805 
       
   806     qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
       
   807            " peer == %s:%i, socket == %s - %s",
       
   808            localAddress.toString().toLatin1().constData(), localPort,
       
   809            peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
       
   810            socketProtocolStr.toLatin1().constData());
       
   811 #endif
       
   812     return true;
       
   813 }
       
   814 
       
   815 void QNativeSocketEnginePrivate::nativeClose()
       
   816 {
       
   817 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   818     qDebug("QNativeSocketEngine::nativeClose()");
       
   819 #endif
       
   820 
       
   821 #ifdef Q_OS_SYMBIAN
       
   822     ::close(socketDescriptor);
       
   823 #else
       
   824 	qt_safe_close(socketDescriptor);
       
   825 #endif
       
   826 }
       
   827 
       
   828 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
       
   829 {
       
   830     Q_Q(QNativeSocketEngine);
       
   831 
       
   832     // ignore the SIGPIPE signal
       
   833     qt_ignore_sigpipe();
       
   834 
       
   835     // loop while ::write() returns -1 and errno == EINTR, in case
       
   836     // of an interrupting signal.
       
   837     ssize_t writtenBytes;
       
   838     do {
       
   839 #ifdef Q_OS_SYMBIAN
       
   840 	    writtenBytes = ::write(socketDescriptor, data, len);
       
   841 #else
       
   842         writtenBytes = qt_safe_write(socketDescriptor, data, len);
       
   843 #endif
       
   844         // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it?
       
   845     } while (writtenBytes < 0 && errno == EINTR);
       
   846 
       
   847     if (writtenBytes < 0) {
       
   848         switch (errno) {
       
   849         case EPIPE:
       
   850         case ECONNRESET:
       
   851             writtenBytes = -1;
       
   852             setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
       
   853             q->close();
       
   854             break;
       
   855         case EAGAIN:
       
   856             writtenBytes = 0;
       
   857             break;
       
   858         case EMSGSIZE:
       
   859             setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
       
   860             break;
       
   861         default:
       
   862             break;
       
   863         }
       
   864     }
       
   865 
       
   866 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   867     qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i",
       
   868            data, qt_prettyDebug(data, qMin((int) len, 16),
       
   869                                 (int) len).data(), len, (int) writtenBytes);
       
   870 #endif
       
   871 
       
   872     return qint64(writtenBytes);
       
   873 }
       
   874 /*
       
   875 */
       
   876 qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
       
   877 {
       
   878     Q_Q(QNativeSocketEngine);
       
   879     if (!q->isValid()) {
       
   880         qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket");
       
   881         return -1;
       
   882     }
       
   883 
       
   884     ssize_t r = 0;
       
   885     do {
       
   886 #ifdef Q_OS_SYMBIAN
       
   887         r = ::read(socketDescriptor, data, maxSize);
       
   888 #else
       
   889         r = qt_safe_read(socketDescriptor, data, maxSize);
       
   890 #endif
       
   891     } while (r == -1 && errno == EINTR);
       
   892 
       
   893     if (r < 0) {
       
   894         r = -1;
       
   895         switch (errno) {
       
   896 #if EWOULDBLOCK-0 && EWOULDBLOCK != EAGAIN
       
   897         case EWOULDBLOCK:
       
   898 #endif
       
   899         case EAGAIN:
       
   900             // No data was available for reading
       
   901             r = -2;
       
   902             break;
       
   903         case EBADF:
       
   904         case EINVAL:
       
   905         case EIO:
       
   906             setError(QAbstractSocket::NetworkError, ReadErrorString);
       
   907             break;
       
   908 #ifdef Q_OS_SYMBIAN
       
   909         case EPIPE:
       
   910 #endif
       
   911         case ECONNRESET:
       
   912 #if defined(Q_OS_VXWORKS)
       
   913         case ESHUTDOWN:
       
   914 #endif
       
   915             r = 0;
       
   916             break;
       
   917         default:
       
   918             break;
       
   919         }
       
   920     }
       
   921 
       
   922 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   923     qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i",
       
   924            data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(),
       
   925            maxSize, r);
       
   926 #endif
       
   927 
       
   928     return qint64(r);
       
   929 }
       
   930 
       
   931 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
       
   932 {
       
   933     fd_set fds;
       
   934     FD_ZERO(&fds);
       
   935     FD_SET(socketDescriptor, &fds);
       
   936 
       
   937     struct timeval tv;
       
   938     tv.tv_sec = timeout / 1000;
       
   939     tv.tv_usec = (timeout % 1000) * 1000;
       
   940 
       
   941 #ifdef Q_OS_SYMBIAN
       
   942     fd_set fdexception;
       
   943     FD_ZERO(&fdexception);
       
   944     FD_SET(socketDescriptor, &fdexception);
       
   945 #endif
       
   946 
       
   947     int retval;
       
   948     if (selectForRead)
       
   949 #ifdef Q_OS_SYMBIAN
       
   950         retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv);
       
   951 #else
       
   952         retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
       
   953 #endif
       
   954     else
       
   955 #ifdef Q_OS_SYMBIAN
       
   956         retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
       
   957 #else
       
   958         retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
       
   959 #endif
       
   960 
       
   961 
       
   962 #ifdef Q_OS_SYMBIAN
       
   963         bool selectForExec = false;
       
   964         if(retval != 0) {
       
   965             if(retval < 0) {
       
   966                 qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
       
   967             }
       
   968             selectForExec = FD_ISSET(socketDescriptor, &fdexception);
       
   969         }
       
   970         if(selectForExec) {
       
   971             qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d",
       
   972                     selectForRead, retval, errno, socketDescriptor);
       
   973             }
       
   974 #endif
       
   975 
       
   976     return retval;
       
   977 }
       
   978 
       
   979 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
       
   980                        bool *selectForRead, bool *selectForWrite) const
       
   981 {
       
   982     fd_set fdread;
       
   983     FD_ZERO(&fdread);
       
   984     if (checkRead)
       
   985         FD_SET(socketDescriptor, &fdread);
       
   986 
       
   987     fd_set fdwrite;
       
   988     FD_ZERO(&fdwrite);
       
   989     if (checkWrite)
       
   990         FD_SET(socketDescriptor, &fdwrite);
       
   991 
       
   992 #ifdef Q_OS_SYMBIAN
       
   993     fd_set fdexception;
       
   994     FD_ZERO(&fdexception);
       
   995     FD_SET(socketDescriptor, &fdexception);
       
   996 #endif
       
   997 
       
   998     struct timeval tv;
       
   999     tv.tv_sec = timeout / 1000;
       
  1000     tv.tv_usec = (timeout % 1000) * 1000;
       
  1001 
       
  1002     int ret;
       
  1003 #ifndef Q_OS_SYMBIAN
       
  1004     ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
       
  1005 #else
       
  1006     QTime timer;
       
  1007     timer.start();
       
  1008 
       
  1009     do {
       
  1010         ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
       
  1011         bool selectForExec = false;
       
  1012         if(ret != 0) {
       
  1013             if(ret < 0) {
       
  1014                 qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
       
  1015             }
       
  1016             selectForExec = FD_ISSET(socketDescriptor, &fdexception);
       
  1017         }
       
  1018         if(selectForExec) {
       
  1019             qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d",
       
  1020                     checkRead, checkWrite, ret, errno, socketDescriptor);
       
  1021             if (checkWrite){
       
  1022                 FD_CLR(socketDescriptor, &fdread);
       
  1023                 FD_SET(socketDescriptor, &fdwrite);
       
  1024             } else if (checkRead)
       
  1025                 FD_SET(socketDescriptor, &fdread);
       
  1026 
       
  1027 
       
  1028             if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE ))
       
  1029                 ret = 1;
       
  1030 
       
  1031         }
       
  1032 
       
  1033         if (ret != -1 || errno != EINTR) {
       
  1034             break;
       
  1035         }
       
  1036 
       
  1037         if (timeout > 0) {
       
  1038             // recalculate the timeout
       
  1039             int t = timeout - timer.elapsed();
       
  1040             if (t < 0) {
       
  1041                 // oops, timeout turned negative?
       
  1042                 ret = -1;
       
  1043                 break;
       
  1044             }
       
  1045 
       
  1046             tv.tv_sec = t / 1000;
       
  1047             tv.tv_usec = (t % 1000) * 1000;
       
  1048         }
       
  1049     } while (true);
       
  1050 #endif
       
  1051 
       
  1052     if (ret <= 0)
       
  1053         return ret;
       
  1054     *selectForRead = FD_ISSET(socketDescriptor, &fdread);
       
  1055     *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
       
  1056 
       
  1057     return ret;
       
  1058 }
       
  1059 
       
  1060 QT_END_NAMESPACE