|
MythTV
0.26-pre
|
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
1.7.6.1