MythTV  0.26-pre
msocketdevice_unix.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the Qt3Support module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License versions 2.0 or 3.0 as published by the Free Software
00009 ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
00010 ** included in the packaging of this file.  Alternatively you may (at
00011 ** your option) use any later version of the GNU General Public
00012 ** License if such license has been publicly approved by Trolltech ASA
00013 ** (or its successors, if any) and the KDE Free Qt Foundation. In
00014 ** addition, as a special exception, Trolltech gives you certain
00015 ** additional rights. These rights are described in the Trolltech GPL
00016 ** Exception version 1.2, which can be found at
00017 ** http://www.trolltech.com/products/qt/gplexception/ and in the file
00018 ** GPL_EXCEPTION.txt in this package.
00019 **
00020 ** Please review the following information to ensure GNU General
00021 ** Public Licensing requirements will be met:
00022 ** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
00023 ** you are unsure which license is appropriate for your use, please
00024 ** review the following information:
00025 ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
00026 ** or contact the sales department at sales@trolltech.com.
00027 **
00028 ** In addition, as a special exception, Trolltech, as the sole
00029 ** copyright holder for Qt Designer, grants users of the Qt/Eclipse
00030 ** Integration plug-in the right for the Qt/Eclipse Integration to
00031 ** link to functionality provided by Qt Designer and its related
00032 ** libraries.
00033 **
00034 ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
00035 ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
00036 ** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
00037 ** granted herein.
00038 **
00039 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00040 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00041 **
00042 ****************************************************************************/
00043 
00044 #include "qplatformdefs.h"
00045 #include "mythlogging.h"
00046 
00047 // Almost always the same. If not, specify in qplatformdefs.h.
00048 #if !defined(QT_SOCKOPTLEN_T)
00049 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
00050 #endif
00051 
00052 // Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
00053 static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
00054 {
00055     return ::accept(s, addr, addrlen);
00056 }
00057 
00058 #if defined(accept)
00059 # undef accept
00060 #endif
00061 
00062 // UnixWare 7 redefines listen -> _listen
00063 static inline int qt_socket_listen(int s, int backlog)
00064 {
00065     return ::listen(s, backlog);
00066 }
00067 
00068 #if defined(listen)
00069 # undef listen
00070 #endif
00071 
00072 // UnixWare 7 redefines socket -> _socket
00073 static inline int qt_socket_socket(int domain, int type, int protocol)
00074 {
00075     return ::socket(domain, type, protocol);
00076 }
00077 
00078 #if defined(socket)
00079 # undef socket
00080 #endif
00081 
00082 #include "msocketdevice.h"
00083 
00084 #include "qwindowdefs.h"
00085 
00086 #include <errno.h>
00087 #include <sys/types.h>
00088 
00089 static inline void qt_socket_getportaddr(struct sockaddr *sa,
00090         quint16 *port, QHostAddress *addr)
00091 {
00092 #if !defined(QT_NO_IPV6)
00093 
00094     if (sa->sa_family == AF_INET6)
00095     {
00096 
00097         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
00098         Q_IPV6ADDR tmp;
00099         memcpy(&tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp));
00100         QHostAddress a(tmp);
00101         *addr = a;
00102         *port = ntohs(sa6->sin6_port);
00103         return;
00104     }
00105 
00106 #endif
00107 
00108     struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
00109 
00110     QHostAddress a(ntohl(sa4->sin_addr.s_addr));
00111 
00112     *port = ntohs(sa4->sin_port);
00113 
00114     *addr = QHostAddress(ntohl(sa4->sin_addr.s_addr));
00115 
00116     return;
00117 }
00118 
00119 // internal
00120 void MSocketDevice::init()
00121 {
00122 }
00123 
00124 
00125 MSocketDevice::Protocol MSocketDevice::getProtocol() const
00126 {
00127     if (isValid())
00128     {
00129 #if !defined (QT_NO_IPV6)
00130 
00131         struct sockaddr_storage sa;
00132 #else
00133 
00134         struct sockaddr sa;
00135 #endif
00136         memset(&sa, 0, sizeof(sa));
00137         QT_SOCKLEN_T sz = sizeof(sa);
00138 #if !defined (QT_NO_IPV6)
00139 
00140         struct sockaddr *sap = reinterpret_cast<struct sockaddr *>(&sa);
00141 
00142         if (!::getsockname(fd, sap, &sz))
00143         {
00144             switch (sap->sa_family)
00145             {
00146 
00147                 case AF_INET:
00148                     return IPv4;
00149 
00150                 case AF_INET6:
00151                     return IPv6;
00152 
00153                 default:
00154                     return Unknown;
00155             }
00156         }
00157 
00158 #else
00159         if (!::getsockname(fd, &sa, &sz))
00160         {
00161             switch (sa.sa_family)
00162             {
00163 
00164                 case AF_INET:
00165                     return IPv4;
00166 
00167                 default:
00168                     return Unknown;
00169             }
00170         }
00171 
00172 #endif
00173     }
00174 
00175     return Unknown;
00176 }
00177 
00185 int MSocketDevice::createNewSocket()
00186 {
00187 #if !defined(QT_NO_IPV6)
00188     int s = qt_socket_socket(protocol() == IPv6 ? AF_INET6 : AF_INET,
00189                              t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
00190 #else
00191     int s = qt_socket_socket(AF_INET, t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
00192 #endif
00193 
00194     if (s < 0)
00195     {
00196         switch (errno)
00197         {
00198 
00199             case EPROTONOSUPPORT:
00200                 e = InternalError; // 0 is supposed to work for both types
00201                 break;
00202 
00203             case ENFILE:
00204                 e = NoFiles; // special case for this
00205                 break;
00206 
00207             case EACCES:
00208                 e = Inaccessible;
00209                 break;
00210 
00211             case ENOBUFS:
00212 
00213             case ENOMEM:
00214                 e = NoResources;
00215                 break;
00216 
00217             case EINVAL:
00218                 e = Impossible;
00219                 break;
00220 
00221             default:
00222                 e = UnknownError;
00223                 break;
00224         }
00225     }
00226     else
00227     {
00228         return s;
00229     }
00230 
00231     return -1;
00232 }
00233 
00247 void MSocketDevice::close()
00248 {
00249     if (fd == -1 || !isOpen())                  // already closed
00250         return;
00251 
00252     setOpenMode(NotOpen);
00253 
00254     ::close(fd);
00255 
00256     LOG(VB_SOCKET, LOG_DEBUG,
00257         QString("MSocketDevice::close: Closed socket %1").arg(fd));
00258 
00259     fd = -1;
00260 
00261     fetchConnectionParameters();
00262 
00263     QIODevice::close();
00264 }
00265 
00266 
00278 bool MSocketDevice::blocking() const
00279 {
00280     if (!isValid())
00281         return true;
00282 
00283     int s = fcntl(fd, F_GETFL, 0);
00284 
00285     return !(s >= 0 && ((s & O_NDELAY) != 0));
00286 }
00287 
00288 
00303 void MSocketDevice::setBlocking(bool enable)
00304 {
00305     LOG(VB_SOCKET, LOG_DEBUG, QString("MSocketDevice::setBlocking(%1)")
00306         .arg((enable) ? "true" : "false"));
00307 
00308     if (!isValid())
00309         return;
00310 
00311     int tmp = ::fcntl(fd, F_GETFL, 0);
00312 
00313     if (tmp >= 0)
00314         tmp = ::fcntl(fd, F_SETFL, enable ? (tmp & ~O_NDELAY) : (tmp | O_NDELAY));
00315 
00316     if (tmp >= 0)
00317         return;
00318 
00319     if (e)
00320         return;
00321 
00322     switch (errno)
00323     {
00324 
00325         case EACCES:
00326 
00327         case EBADF:
00328             e = Impossible;
00329             break;
00330 
00331         case EFAULT:
00332 
00333         case EAGAIN:
00334 #if EAGAIN != EWOULDBLOCK
00335 
00336         case EWOULDBLOCK:
00337 #endif
00338 
00339         case EDEADLK:
00340 
00341         case EINTR:
00342 
00343         case EINVAL:
00344 
00345         case EMFILE:
00346 
00347         case ENOLCK:
00348 
00349         case EPERM:
00350 
00351         default:
00352             e = UnknownError;
00353     }
00354 }
00355 
00356 
00360 int MSocketDevice::option(Option opt) const
00361 {
00362     if (!isValid())
00363         return -1;
00364 
00365     int n = -1;
00366 
00367     int v = -1;
00368 
00369     switch (opt)
00370     {
00371 
00372         case Broadcast:
00373             n = SO_BROADCAST;
00374             break;
00375 
00376         case ReceiveBuffer:
00377             n = SO_RCVBUF;
00378             break;
00379 
00380         case ReuseAddress:
00381             n = SO_REUSEADDR;
00382             break;
00383 
00384         case SendBuffer:
00385             n = SO_SNDBUF;
00386             break;
00387 
00388         case Keepalive:
00389             n = SO_KEEPALIVE;
00390             break;
00391     }
00392 
00393     if (n != -1)
00394     {
00395         QT_SOCKOPTLEN_T len;
00396         len = sizeof(v);
00397         int r = ::getsockopt(fd, SOL_SOCKET, n, (char*) & v, &len);
00398 
00399         if (r >= 0)
00400             return v;
00401 
00402         if (!e)
00403         {
00404             MSocketDevice *that = (MSocketDevice*)this; // mutable function
00405 
00406             switch (errno)
00407             {
00408 
00409                 case EBADF:
00410 
00411                 case ENOTSOCK:
00412                     that->e = Impossible;
00413                     break;
00414 
00415                 case EFAULT:
00416                     that->e = InternalError;
00417                     break;
00418 
00419                 default:
00420                     that->e = UnknownError;
00421                     break;
00422             }
00423         }
00424 
00425         return -1;
00426     }
00427 
00428     return v;
00429 }
00430 
00431 
00435 void MSocketDevice::setOption(Option opt, int v)
00436 {
00437     if (!isValid())
00438         return;
00439 
00440     int n = -1; // for really, really bad compilers
00441 
00442     switch (opt)
00443     {
00444 
00445         case Broadcast:
00446             n = SO_BROADCAST;
00447             break;
00448 
00449         case ReceiveBuffer:
00450             n = SO_RCVBUF;
00451             break;
00452 
00453         case ReuseAddress:
00454             n = SO_REUSEADDR;
00455             break;
00456 
00457         case SendBuffer:
00458             n = SO_SNDBUF;
00459             break;
00460 
00461         case Keepalive:
00462             n = SO_KEEPALIVE;
00463             break;
00464 
00465         default:
00466             return;
00467     }
00468 
00469     if (::setsockopt(fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 &&
00470             e == NoError)
00471     {
00472         switch (errno)
00473         {
00474 
00475             case EBADF:
00476 
00477             case ENOTSOCK:
00478                 e = Impossible;
00479                 break;
00480 
00481             case EFAULT:
00482                 e = InternalError;
00483                 break;
00484 
00485             default:
00486                 e = UnknownError;
00487                 break;
00488         }
00489     }
00490 }
00491 
00492 
00502 bool MSocketDevice::connect(const QHostAddress &addr, quint16 port)
00503 {
00504     if (isValid() && addr.protocol() != pa.protocol())
00505     {
00506         close();
00507         fd = -1;
00508     }
00509 
00510     if (!isValid())
00511     {
00512 #if !defined(QT_NO_IPV6)
00513 
00514         if (addr.protocol() == QAbstractSocket::IPv6Protocol)
00515         {
00516             setProtocol(IPv6);
00517             LOG(VB_SOCKET, LOG_INFO,
00518                 "MSocketDevice::connect: setting Protocol to IPv6");
00519         }
00520         else
00521 #endif
00522             if (addr.protocol() == QAbstractSocket::IPv4Protocol)
00523             {
00524                 setProtocol(IPv4);
00525                 LOG(VB_SOCKET, LOG_INFO,
00526                     "MSocketDevice::connect: setting Protocol to IPv4");
00527             }
00528 
00529         LOG(VB_SOCKET, LOG_INFO,
00530 
00531             "MSocketDevice::connect: attempting to create new socket");
00532         MSocketDevice::setSocket(createNewSocket(), t);
00533 
00534         // If still not valid, give up.
00535 
00536         if (!isValid())
00537             return false;
00538     }
00539 
00540     pa = addr;
00541 
00542     pp = port;
00543 
00544     struct sockaddr_in a4;
00545 
00546     struct sockaddr *aa;
00547     QT_SOCKLEN_T aalen;
00548 
00549 #if !defined(QT_NO_IPV6)
00550 
00551     struct sockaddr_in6 a6;
00552 
00553     if (addr.protocol() == QAbstractSocket::IPv6Protocol)
00554     {
00555         memset(&a6, 0, sizeof(a6));
00556         a6.sin6_family = AF_INET6;
00557         a6.sin6_port = htons(port);
00558         Q_IPV6ADDR ip6 = addr.toIPv6Address();
00559         memcpy(&a6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
00560 
00561         aalen = sizeof(a6);
00562         aa = (struct sockaddr *) & a6;
00563     }
00564     else
00565 #endif
00566         if (addr.protocol() == QAbstractSocket::IPv4Protocol)
00567         {
00568             memset(&a4, 0, sizeof(a4));
00569             a4.sin_family = AF_INET;
00570             a4.sin_port = htons(port);
00571             a4.sin_addr.s_addr = htonl(addr.toIPv4Address());
00572 
00573             aalen = sizeof(a4);
00574             aa = (struct sockaddr *) & a4;
00575         }
00576         else
00577         {
00578             e = Impossible;
00579             return false;
00580         }
00581 
00582     int r = QT_SOCKET_CONNECT(fd, aa, aalen);
00583 
00584     if (r == 0)
00585     {
00586         fetchConnectionParameters();
00587         return true;
00588     }
00589 
00590     if (errno == EISCONN || errno == EALREADY || errno == EINPROGRESS)
00591     {
00592         fetchConnectionParameters();
00593         return true;
00594     }
00595 
00596     if (e != NoError || errno == EAGAIN || errno == EWOULDBLOCK)
00597     {
00598         return false;
00599     }
00600 
00601     switch (errno)
00602     {
00603 
00604         case EBADF:
00605 
00606         case ENOTSOCK:
00607             e = Impossible;
00608             break;
00609 
00610         case EFAULT:
00611 
00612         case EAFNOSUPPORT:
00613             e = InternalError;
00614             break;
00615 
00616         case ECONNREFUSED:
00617             e = ConnectionRefused;
00618             break;
00619 
00620         case ETIMEDOUT:
00621 
00622         case ENETUNREACH:
00623             e = NetworkFailure;
00624             break;
00625 
00626         case EADDRINUSE:
00627             e = NoResources;
00628             break;
00629 
00630         case EACCES:
00631 
00632         case EPERM:
00633             e = Inaccessible;
00634             break;
00635 
00636         default:
00637             e = UnknownError;
00638             break;
00639     }
00640 
00641     return false;
00642 }
00643 
00644 
00654 bool MSocketDevice::bind(const QHostAddress &address, quint16 port)
00655 {
00656     if (!isValid())
00657         return false;
00658 
00659     int r;
00660 
00661     struct sockaddr_in a4;
00662 
00663 #if !defined(QT_NO_IPV6)
00664 
00665     struct sockaddr_in6 a6;
00666 
00667     if (address.protocol() == QAbstractSocket::IPv6Protocol)
00668     {
00669         memset(&a6, 0, sizeof(a6));
00670         a6.sin6_family = AF_INET6;
00671         a6.sin6_port = htons(port);
00672         Q_IPV6ADDR tmp = address.toIPv6Address();
00673         memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
00674 
00675         r = QT_SOCKET_BIND(fd, (struct sockaddr *) & a6, sizeof(a6));
00676     }
00677     else
00678 #endif
00679         if (address.protocol() == QAbstractSocket::IPv4Protocol)
00680         {
00681             memset(&a4, 0, sizeof(a4));
00682             a4.sin_family = AF_INET;
00683             a4.sin_port = htons(port);
00684             a4.sin_addr.s_addr = htonl(address.toIPv4Address());
00685 
00686             r = QT_SOCKET_BIND(fd, (struct sockaddr*) & a4, sizeof(a4));
00687         }
00688         else
00689         {
00690             e = Impossible;
00691             return false;
00692         }
00693 
00694     if (r < 0)
00695     {
00696         switch (errno)
00697         {
00698 
00699             case EINVAL:
00700                 e = AlreadyBound;
00701                 break;
00702 
00703             case EACCES:
00704                 e = Inaccessible;
00705                 break;
00706 
00707             case ENOMEM:
00708                 e = NoResources;
00709                 break;
00710 
00711             case EFAULT: // a was illegal
00712 
00713             case ENAMETOOLONG: // sz was wrong
00714                 e = InternalError;
00715                 break;
00716 
00717             case EBADF: // AF_UNIX only
00718 
00719             case ENOTSOCK: // AF_UNIX only
00720 
00721             case EROFS: // AF_UNIX only
00722 
00723             case ENOENT: // AF_UNIX only
00724 
00725             case ENOTDIR: // AF_UNIX only
00726 
00727             case ELOOP: // AF_UNIX only
00728                 e = Impossible;
00729                 break;
00730 
00731             default:
00732                 e = UnknownError;
00733                 break;
00734         }
00735 
00736         return false;
00737     }
00738 
00739     fetchConnectionParameters();
00740 
00741     return true;
00742 }
00743 
00744 
00756 bool MSocketDevice::listen(int backlog)
00757 {
00758     if (!isValid())
00759         return false;
00760 
00761     if (qt_socket_listen(fd, backlog) >= 0)
00762         return true;
00763 
00764     if (!e)
00765         e = Impossible;
00766 
00767     return false;
00768 }
00769 
00770 
00778 int MSocketDevice::accept()
00779 {
00780     if (!isValid())
00781         return -1;
00782 
00783 #if !defined (QT_NO_IPV6)
00784 
00785     struct sockaddr_storage aa;
00786 
00787 #else
00788 
00789     struct sockaddr aa;
00790 
00791 #endif
00792     QT_SOCKLEN_T l = sizeof(aa);
00793 
00794     bool done;
00795 
00796     int s;
00797 
00798     do
00799     {
00800         s = qt_socket_accept(fd, (struct sockaddr*) & aa, &l);
00801         // we'll blithely throw away the stuff accept() wrote to aa
00802         done = true;
00803 
00804         if (s < 0 && e == NoError)
00805         {
00806             switch (errno)
00807             {
00808 
00809                 case EINTR:
00810                     done = false;
00811                     break;
00812 #if defined(EPROTO)
00813 
00814                 case EPROTO:
00815 #endif
00816 #if defined(ENONET)
00817 
00818                 case ENONET:
00819 #endif
00820 
00821                 case ENOPROTOOPT:
00822 
00823                 case EHOSTDOWN:
00824 
00825                 case EOPNOTSUPP:
00826 
00827                 case EHOSTUNREACH:
00828 
00829                 case ENETDOWN:
00830 
00831                 case ENETUNREACH:
00832 
00833                 case ETIMEDOUT:
00834                     // in all these cases, an error happened during connection
00835                     // setup.  we're not interested in what happened, so we
00836                     // just treat it like the client-closed-quickly case.
00837 
00838                 case EPERM:
00839                     // firewalling wouldn't let us accept.  we treat it like
00840                     // the client-closed-quickly case.
00841 
00842                 case EAGAIN:
00843 #if EAGAIN != EWOULDBLOCK
00844 
00845                 case EWOULDBLOCK:
00846 #endif
00847                     // the client closed the connection before we got around
00848                     // to accept()ing it.
00849                     break;
00850 
00851                 case EBADF:
00852 
00853                 case ENOTSOCK:
00854                     e = Impossible;
00855                     break;
00856 
00857                 case EFAULT:
00858                     e = InternalError;
00859                     break;
00860 
00861                 case ENOMEM:
00862 
00863                 case ENOBUFS:
00864                     e = NoResources;
00865                     break;
00866 
00867                 default:
00868                     e = UnknownError;
00869                     break;
00870             }
00871         }
00872     }
00873     while (!done);
00874 
00875     return s;
00876 }
00877 
00878 
00890 qint64 MSocketDevice::bytesAvailable() const
00891 {
00892     if (!isValid())
00893         return -1;
00894 
00895     /*
00896       Apparently, there is not consistency among different operating
00897       systems on how to use FIONREAD.
00898 
00899       FreeBSD, Linux and Solaris all expect the 3rd argument to
00900       ioctl() to be an int, which is normally 32-bit even on 64-bit
00901       machines.
00902 
00903       IRIX, on the other hand, expects a size_t, which is 64-bit on
00904       64-bit machines.
00905 
00906       So, the solution is to use size_t initialized to zero to make
00907       sure all bits are set to zero, preventing underflow with the
00908       FreeBSD/Linux/Solaris ioctls.
00909     */
00910     union { size_t st;
00911         int i;
00912     } nbytes;
00913 
00914     nbytes.st = 0;
00915 
00916     // gives shorter than true amounts on Unix domain sockets.
00917 
00918     if (::ioctl(fd, FIONREAD, (char*)&nbytes.i) < 0)
00919         return -1;
00920 
00921     return (qint64) nbytes.i + QIODevice::bytesAvailable();
00922 }
00923 
00924 
00943 qint64 MSocketDevice::waitForMore(int msecs, bool *timeout) const
00944 {
00945     if (!isValid())
00946         return -1;
00947 
00948     if (fd >= FD_SETSIZE)
00949         return -1;
00950 
00951     fd_set fds;
00952 
00953     struct timeval tv;
00954 
00955     FD_ZERO(&fds);
00956 
00957     FD_SET(fd, &fds);
00958 
00959     tv.tv_sec = msecs / 1000;
00960 
00961     tv.tv_usec = (msecs % 1000) * 1000;
00962 
00963     int rv = select(fd + 1, &fds, 0, 0, msecs < 0 ? 0 : &tv);
00964 
00965     if (rv < 0)
00966         return -1;
00967 
00968     if (timeout)
00969     {
00970         if (rv == 0)
00971             *timeout = true;
00972         else
00973             *timeout = false;
00974     }
00975 
00976     return bytesAvailable();
00977 }
00978 
00979 
00984 qint64 MSocketDevice::readData(char *data, qint64 maxlen)
00985 {
00986     if (maxlen == 0)
00987         return 0;
00988 
00989     if (data == 0)
00990     {
00991         LOG(VB_SOCKET, LOG_DEBUG,
00992             "MSocketDevice::readBlock: Null pointer error");
00993         return -1;
00994     }
00995 
00996     if (!isValid())
00997     {
00998         LOG(VB_SOCKET, LOG_DEBUG,
00999             "MSocketDevice::readBlock: Invalid socket");
01000         return -1;
01001     }
01002 
01003     if (!isOpen())
01004     {
01005         LOG(VB_SOCKET, LOG_DEBUG,
01006             "MSocketDevice::readBlock: Device is not open");
01007         return -1;
01008     }
01009 
01010     if (!isReadable())
01011     {
01012         LOG(VB_SOCKET, LOG_DEBUG,
01013             "MSocketDevice::readBlock: Read operation not permitted");
01014         return -1;
01015     }
01016 
01017     bool done = false;
01018 
01019     int r = 0;
01020 
01021     while (done == false)
01022     {
01023         if (t == Datagram)
01024         {
01025 #if !defined(QT_NO_IPV6)
01026 
01027             struct sockaddr_storage aa;
01028 #else
01029 
01030             struct sockaddr_in aa;
01031 #endif
01032             memset(&aa, 0, sizeof(aa));
01033             QT_SOCKLEN_T sz;
01034             sz = sizeof(aa);
01035             r = ::recvfrom(fd, data, maxlen, 0,
01036                            (struct sockaddr *) & aa, &sz);
01037 
01038             qt_socket_getportaddr((struct sockaddr *)&aa, &pp, &pa);
01039 
01040         }
01041         else
01042         {
01043             r = ::read(fd, data, maxlen);
01044         }
01045 
01046         done = true;
01047 
01048         if (r == 0 && t == Stream && maxlen > 0)
01049         {
01050             // connection closed
01051             close();
01052         }
01053         else if (r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
01054         {
01055             // nothing
01056         }
01057         else if (errno == EINTR)
01058         {
01059             done = false;
01060         }
01061         else if (e == NoError)
01062         {
01063             switch (errno)
01064             {
01065 
01066                 case EIO:
01067 
01068                 case EISDIR:
01069 
01070                 case EBADF:
01071 
01072                 case EINVAL:
01073 
01074                 case EFAULT:
01075 
01076                 case ENOTCONN:
01077 
01078                 case ENOTSOCK:
01079                     e = Impossible;
01080                     break;
01081 #if defined(ENONET)
01082 
01083                 case ENONET:
01084 #endif
01085 
01086                 case EHOSTUNREACH:
01087 
01088                 case ENETDOWN:
01089 
01090                 case ENETUNREACH:
01091 
01092                 case ETIMEDOUT:
01093                     e = NetworkFailure;
01094                     break;
01095 
01096                 case EPIPE:
01097 
01098                 case ECONNRESET:
01099                     // connection closed
01100                     close();
01101                     r = 0;
01102                     break;
01103 
01104                 default:
01105                     e = UnknownError;
01106                     break;
01107             }
01108         }
01109     }
01110 
01111     return r;
01112 }
01113 
01114 
01121 qint64 MSocketDevice::writeData(const char *data, qint64 len)
01122 {
01123     if (len == 0)
01124         return 0;
01125 
01126     if (data == 0)
01127     {
01128         LOG(VB_SOCKET, LOG_DEBUG,
01129             "MSocketDevice::writeBlock: Null pointer error");
01130         return -1;
01131     }
01132 
01133     if (!isValid())
01134     {
01135         LOG(VB_SOCKET, LOG_DEBUG,
01136             "MSocketDevice::writeBlock: Invalid socket");
01137         return -1;
01138     }
01139 
01140     if (!isOpen())
01141     {
01142         LOG(VB_SOCKET, LOG_DEBUG,
01143             "MSocketDevice::writeBlock: Device is not open");
01144         return -1;
01145     }
01146 
01147     if (!isWritable())
01148     {
01149         LOG(VB_SOCKET, LOG_DEBUG,
01150             "MSocketDevice::writeBlock: Write operation not permitted");
01151         return -1;
01152     }
01153 
01154     bool done = false;
01155 
01156     int r = 0;
01157     bool timeout;
01158 
01159     while (!done)
01160     {
01161         r = ::write(fd, data, len);
01162         done = true;
01163 
01164         if (r < 0 && e == NoError &&
01165                 errno != EAGAIN && errno != EWOULDBLOCK)
01166         {
01167             switch (errno)
01168             {
01169 
01170                 case EINTR: // signal - call read() or whatever again
01171                     done = false;
01172                     break;
01173 
01174                 case EPIPE:
01175 
01176                 case ECONNRESET:
01177                     // connection closed
01178                     close();
01179                     r = 0;
01180                     break;
01181 
01182                 case ENOSPC:
01183 
01184                 case EIO:
01185 
01186                 case EISDIR:
01187 
01188                 case EBADF:
01189 
01190                 case EINVAL:
01191 
01192                 case EFAULT:
01193 
01194                 case ENOTCONN:
01195 
01196                 case ENOTSOCK:
01197                     e = Impossible;
01198                     break;
01199 #if defined(ENONET)
01200 
01201                 case ENONET:
01202 #endif
01203 
01204                 case EHOSTUNREACH:
01205 
01206                 case ENETDOWN:
01207 
01208                 case ENETUNREACH:
01209 
01210                 case ETIMEDOUT:
01211                     e = NetworkFailure;
01212                     break;
01213 
01214                 default:
01215                     e = UnknownError;
01216                     break;
01217             }
01218         }
01219         else if (waitForMore(0, &timeout) == 0)
01220         {
01221             if (!timeout)
01222             {
01223                 // connection closed
01224                 close();
01225             }
01226         }
01227     }
01228 
01229     return r;
01230 }
01231 
01232 
01242 qint64 MSocketDevice::writeBlock(const char * data, quint64 len,
01243                                  const QHostAddress & host, quint16 port)
01244 {
01245     if (len == 0)
01246         return 0;
01247 
01248     if (t != Datagram)
01249     {
01250         LOG(VB_SOCKET, LOG_DEBUG,
01251             "MSocketDevice::sendBlock: Not datagram");
01252         return -1; // for now - later we can do t/tcp
01253     }
01254 
01255     if (data == 0)
01256     {
01257         LOG(VB_SOCKET, LOG_DEBUG,
01258             "MSocketDevice::sendBlock: Null pointer error");
01259         return -1;
01260     }
01261 
01262     if (!isValid())
01263     {
01264         LOG(VB_SOCKET, LOG_DEBUG,
01265             "MSocketDevice::sendBlock: Invalid socket");
01266         return -1;
01267     }
01268 
01269     if (!isOpen())
01270     {
01271         LOG(VB_SOCKET, LOG_DEBUG,
01272             "MSocketDevice::sendBlock: Device is not open");
01273         return -1;
01274     }
01275 
01276     if (!isWritable())
01277     {
01278         LOG(VB_SOCKET, LOG_DEBUG,
01279             "MSocketDevice::sendBlock: Write operation not permitted");
01280         return -1;
01281     }
01282 
01283     struct sockaddr_in a4;
01284 
01285     struct sockaddr *aa;
01286 
01287     QT_SOCKLEN_T slen;
01288 
01289 #if !defined(QT_NO_IPV6)
01290 
01291     struct sockaddr_in6 a6;
01292 
01293     if (host.protocol() == QAbstractSocket::IPv6Protocol)
01294     {
01295         memset(&a6, 0, sizeof(a6));
01296         a6.sin6_family = AF_INET6;
01297         a6.sin6_port = htons(port);
01298 
01299         Q_IPV6ADDR tmp = host.toIPv6Address();
01300         memcpy(&a6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
01301         slen = sizeof(a6);
01302         aa = (struct sockaddr *) & a6;
01303     }
01304     else
01305 #endif
01306         if (host.protocol() == QAbstractSocket::IPv4Protocol)
01307         {
01308             memset(&a4, 0, sizeof(a4));
01309             a4.sin_family = AF_INET;
01310             a4.sin_port = htons(port);
01311             a4.sin_addr.s_addr = htonl(host.toIPv4Address());
01312             slen = sizeof(a4);
01313             aa = (struct sockaddr *) & a4;
01314         }
01315         else
01316         {
01317             e = Impossible;
01318             return -1;
01319         }
01320 
01321     // we'd use MSG_DONTWAIT + MSG_NOSIGNAL if Stevens were right.
01322     // but apparently Stevens and most implementors disagree
01323     bool done = false;
01324 
01325     int r = 0;
01326 
01327     while (!done)
01328     {
01329         r = ::sendto(fd, data, len, 0, aa, slen);
01330         done = true;
01331 
01332         if (r < 0 && e == NoError &&
01333                 errno != EAGAIN && errno != EWOULDBLOCK)
01334         {
01335             switch (errno)
01336             {
01337 
01338                 case EINTR: // signal - call read() or whatever again
01339                     done = false;
01340                     break;
01341 
01342                 case ENOSPC:
01343 
01344                 case EPIPE:
01345 
01346                 case EIO:
01347 
01348                 case EISDIR:
01349 
01350                 case EBADF:
01351 
01352                 case EINVAL:
01353 
01354                 case EFAULT:
01355 
01356                 case ENOTCONN:
01357 
01358                 case ENOTSOCK:
01359                     e = Impossible;
01360                     break;
01361 #if defined(ENONET)
01362 
01363                 case ENONET:
01364 #endif
01365 
01366                 case EHOSTUNREACH:
01367 
01368                 case ENETDOWN:
01369 
01370                 case ENETUNREACH:
01371 
01372                 case ETIMEDOUT:
01373                     e = NetworkFailure;
01374                     break;
01375 
01376                 default:
01377                     e = UnknownError;
01378                     break;
01379             }
01380         }
01381     }
01382 
01383     return r;
01384 }
01385 
01386 
01391 void MSocketDevice::fetchConnectionParameters()
01392 {
01393     if (!isValid())
01394     {
01395         p = 0;
01396         a = QHostAddress();
01397         pp = 0;
01398         pa = QHostAddress();
01399         return;
01400     }
01401 
01402 #if !defined(QT_NO_IPV6)
01403 
01404     struct sockaddr_storage sa;
01405 
01406 #else
01407 
01408     struct sockaddr_in sa;
01409 
01410 #endif
01411     memset(&sa, 0, sizeof(sa));
01412 
01413     QT_SOCKLEN_T sz;
01414 
01415     sz = sizeof(sa);
01416 
01417     if (!::getsockname(fd, (struct sockaddr *)(&sa), &sz))
01418         qt_socket_getportaddr((struct sockaddr *)&sa, &p, &a);
01419 
01420     sz = sizeof(sa);
01421 
01422     if (!::getpeername(fd, (struct sockaddr *)(&sa), &sz))
01423         qt_socket_getportaddr((struct sockaddr *)&sa, &pp, &pa);
01424 }
01425 
01426 
01435 quint16 MSocketDevice::peerPort() const
01436 {
01437     return pp;
01438 }
01439 
01440 
01449 QHostAddress MSocketDevice::peerAddress() const
01450 {
01451     return pa;
01452 }
01453 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends