Changeset 561 for trunk/src/network/socket/qnativesocketengine_unix.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/network/socket/qnativesocketengine_unix.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information ([email protected]) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation ([email protected]) 5 6 ** 6 7 ** This file is part of the QtNetwork module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 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 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you 37 ** @nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 41 41 42 42 //#define QNATIVESOCKETENGINE_DEBUG 43 44 43 #include "qnativesocketengine_p.h" 44 45 45 #include "qiodevice.h" 46 46 #include "qhostaddress.h" … … 63 63 #include <qstring.h> 64 64 #include <ctype.h> 65 66 67 68 69 70 71 65 72 #endif 66 73 … … 101 108 static void qt_ignore_sigpipe() 102 109 { 110 103 111 // Set to ignore SIGPIPE once only. 104 112 static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0); … … 109 117 ::sigaction(SIGPIPE, &noaction, 0); 110 118 } 119 120 121 122 111 123 } 112 124 … … 115 127 \a port and \a addr if they are non-null. 116 128 */ 117 static inline void qt_socket_getPortAndAddress( struct sockaddr *sa, quint16 *port, QHostAddress *addr)129 static inline void qt_socket_getPortAndAddress(, quint16 *port, QHostAddress *addr) 118 130 { 119 131 #if !defined(QT_NO_IPV6) 120 if (sa->sa_family == AF_INET6) { 121 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 132 if (s->a.sa_family == AF_INET6) { 122 133 Q_IPV6ADDR tmp; 123 memcpy(&tmp, &s a6->sin6_addr.s6_addr, sizeof(tmp));134 memcpy(&tmp, &s6_addr, sizeof(tmp)); 124 135 if (addr) { 125 136 QHostAddress tmpAddress; … … 128 139 #ifndef QT_NO_IPV6IFNAME 129 140 char scopeid[IFNAMSIZ]; 130 if (::if_indextoname(s a6->sin6_scope_id, scopeid) > 0) {141 if (::if_indextoname(s) { 131 142 addr->setScopeId(QLatin1String(scopeid)); 132 143 } else 133 144 #endif 134 addr->setScopeId(QString::number(s a6->sin6_scope_id));145 addr->setScopeId(QString::number(ssin6_scope_id)); 135 146 } 136 147 if (port) 137 *port = ntohs(s a6->sin6_port);148 *port = ntohs(ssin6_port); 138 149 return; 139 150 } 140 151 #endif 141 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;142 152 if (port) 143 *port = ntohs(s a4->sin_port);153 *port = ntohs(ssin_port); 144 154 if (addr) { 145 155 QHostAddress tmpAddress; 146 tmpAddress.setAddress(ntohl(s a4->sin_addr.s_addr));156 tmpAddress.setAddress(ntohl(ssin_addr.s_addr)); 147 157 *addr = tmpAddress; 148 158 } … … 164 174 #endif 165 175 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM; 166 int socket = qt_socket_socket(protocol, type, 0); 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 167 181 168 182 if (socket <= 0) { … … 191 205 // Ensure that the socket is closed on exec*(). 192 206 ::fcntl(socket, F_SETFD, FD_CLOEXEC); 207 193 208 socketDescriptor = socket; 194 209 return true; … … 205 220 206 221 int n = -1; 222 223 207 224 switch (opt) { 208 225 case QNativeSocketEngine::ReceiveBufferSocketOption: … … 224 241 n = SO_OOBINLINE; 225 242 break; 243 244 245 246 247 248 249 226 250 } 227 251 228 252 int v = -1; 229 253 QT_SOCKOPTLEN_T len = sizeof(v); 230 if ( getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1)254 if (, n, (char *) &v, &len) != -1) 231 255 return v; 256 232 257 return -1; 233 258 } … … 244 269 245 270 int n = 0; 271 272 246 273 switch (opt) { 247 274 case QNativeSocketEngine::ReceiveBufferSocketOption: … … 256 283 case QNativeSocketEngine::NonBlockingSocketOption: { 257 284 // Make the socket nonblocking. 285 258 286 int flags = ::fcntl(socketDescriptor, F_GETFL, 0); 259 287 if (flags == -1) { … … 269 297 return false; 270 298 } 271 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 272 312 return true; 273 313 } 274 314 case QNativeSocketEngine::AddressReusable: 275 #if def SO_REUSEPORT315 #if 276 316 n = SO_REUSEPORT; 277 317 #else … … 284 324 n = SO_OOBINLINE; 285 325 break; 286 } 287 288 return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0; 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; 289 336 } 290 337 291 338 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) 292 339 { 340 341 342 343 293 344 struct sockaddr_in sockAddrIPv4; 294 345 struct sockaddr *sockAddrPtr = 0; … … 328 379 // unreachable 329 380 } 330 331 int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize); 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 332 386 if (connectResult == -1) { 333 387 switch (errno) { … … 433 487 434 488 int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize); 489 435 490 if (bindResult < 0) { 436 491 switch(errno) { … … 469 524 bool QNativeSocketEnginePrivate::nativeListen(int backlog) 470 525 { 471 if (qt_socket_listen(socketDescriptor, backlog) < 0) { 526 #ifdef Q_OS_SYMBIAN 527 if (::listen(socketDescriptor, backlog) < 0) { 528 #else 529 if (qt_safe_listen(socketDescriptor, backlog) < 0) { 530 #endif 472 531 switch (errno) { 473 532 case EADDRINUSE: … … 496 555 int QNativeSocketEnginePrivate::nativeAccept() 497 556 { 498 int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0); 499 #if defined (QNATIVESOCKETENGINE_DEBUG) 500 qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor); 501 #endif 502 // Ensure that the socket is closed on exec*() 503 ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC); 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 504 573 return acceptedDescriptor; 505 574 } … … 507 576 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const 508 577 { 509 /* 510 Apparently, there is not consistency among different operating 511 systems on how to use FIONREAD. 512 513 FreeBSD, Linux and Solaris all expect the 3rd argument to 514 ioctl() to be an int, which is normally 32-bit even on 64-bit 515 machines. 516 517 IRIX, on the other hand, expects a size_t, which is 64-bit on 518 64-bit machines. 519 520 So, the solution is to use size_t initialized to zero to make 521 sure all bits are set to zero, preventing underflow with the 522 FreeBSD/Linux/Solaris ioctls. 523 */ 524 size_t nbytes = 0; 578 int nbytes = 0; 525 579 // gives shorter than true amounts on Unix domain sockets. 526 580 qint64 available = 0; 527 if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0) 528 available = (qint64) *((int *) &nbytes); 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; 529 587 530 588 #if defined (QNATIVESOCKETENGINE_DEBUG) … … 537 595 { 538 596 // Create a sockaddr struct and reset its port number. 539 #if !defined(QT_NO_IPV6) 540 struct sockaddr_storage storage; 541 sockaddr_in6 *storagePtrIPv6 = reinterpret_cast<sockaddr_in6 *>(&storage); 542 storagePtrIPv6->sin6_port = 0; 543 #else 544 struct sockaddr storage; 545 #endif 546 sockaddr *storagePtr = reinterpret_cast<sockaddr *>(&storage); 547 storagePtr->sa_family = 0; 548 549 sockaddr_in *storagePtrIPv4 = reinterpret_cast<sockaddr_in *>(&storage); 550 storagePtrIPv4->sin_port = 0; 597 qt_sockaddr storage; 551 598 QT_SOCKLEN_T storageSize = sizeof(storage); 599 552 600 553 601 // Peek 0 bytes into the next message. The size of the message may … … 556 604 do { 557 605 char c; 558 readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, storagePtr, &storageSize);606 readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, , &storageSize); 559 607 } while (readBytes == -1 && errno == EINTR); 560 608 … … 570 618 } 571 619 620 621 622 623 624 625 626 627 572 628 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const 573 629 { 574 630 QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192); 575 631 ssize_t recvResult = -1; 632 576 633 for (;;) { 577 634 // the data written to udpMessagePeekBuffer is discarded, so … … 579 636 // so. 580 637 recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(), 581 638 udpMessagePeekBuffer.size(), MSG_PEEK); 582 639 if (recvResult == -1 && errno == EINTR) 583 640 continue; … … 595 652 return qint64(recvResult); 596 653 } 597 654 #endif 598 655 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, 599 656 QHostAddress *address, quint16 *port) 600 657 { 601 #if !defined(QT_NO_IPV6) 602 struct sockaddr_storage aa; 603 #else 604 struct sockaddr_in aa; 605 #endif 658 qt_sockaddr aa; 606 659 memset(&aa, 0, sizeof(aa)); 607 660 QT_SOCKLEN_T sz; … … 612 665 char c; 613 666 recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, 614 0, (struct sockaddr *)&aa, &sz);667 0, a, &sz); 615 668 } while (recvFromResult == -1 && errno == EINTR); 616 669 … … 618 671 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); 619 672 } else if (port || address) { 620 qt_socket_getPortAndAddress( (struct sockaddr *)&aa, port, address);673 qt_socket_getPortAndAddress(&aa, port, address); 621 674 } 622 675 … … 641 694 struct sockaddr_in6 sockAddrIPv6; 642 695 if (host.protocol() == QAbstractSocket::IPv6Protocol) { 643 644 645 646 647 648 649 650 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; 651 704 } else 652 705 #endif 653 706 if (host.protocol() == QAbstractSocket::IPv4Protocol) { 654 655 656 657 658 659 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; 660 713 } 661 714 662 715 // ignore the SIGPIPE signal 663 716 qt_ignore_sigpipe(); 664 665 ssize_t sentBytes; 666 do { 667 sentBytes = ::sendto(socketDescriptor, data, len, 668 0, sockAddrPtr, sockAddrSize); 669 } while (sentBytes == -1 && errno == EINTR); 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 670 724 671 725 if (sentBytes < 0) { … … 698 752 return false; 699 753 700 #if !defined(QT_NO_IPV6) 701 struct sockaddr_storage sa; 702 #else 703 struct sockaddr_in sa; 704 #endif 705 struct sockaddr *sockAddrPtr = (struct sockaddr *) &sa; 754 qt_sockaddr sa; 706 755 QT_SOCKLEN_T sockAddrSize = sizeof(sa); 707 756 708 757 // Determine local address 709 758 memset(&sa, 0, sizeof(sa)); 710 if (::getsockname(socketDescriptor, sockAddrPtr, &sockAddrSize) == 0) {711 qt_socket_getPortAndAddress( sockAddrPtr, &localPort, &localAddress);759 if (::getsockname(socketDescriptor, , &sockAddrSize) == 0) { 760 qt_socket_getPortAndAddress(, &localPort, &localAddress); 712 761 713 762 // Determine protocol family 714 switch (s ockAddrPtr->sa_family) {763 switch (ssa_family) { 715 764 case AF_INET: 716 765 socketProtocol = QAbstractSocket::IPv4Protocol; … … 732 781 733 782 // Determine the remote address 734 if (!::getpeername(socketDescriptor, sockAddrPtr, &sockAddrSize))735 qt_socket_getPortAndAddress( sockAddrPtr, &peerPort, &peerAddress);783 if (!::getpeername(socketDescriptor, , &sockAddrSize)) 784 qt_socket_getPortAndAddress(, &peerPort, &peerAddress); 736 785 737 786 // Determine the socket type (UDP/TCP) … … 769 818 qDebug("QNativeSocketEngine::nativeClose()"); 770 819 #endif 820 821 771 822 ::close(socketDescriptor); 823 824 825 772 826 } 773 827 … … 783 837 ssize_t writtenBytes; 784 838 do { 785 writtenBytes = ::write(socketDescriptor, data, len); 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? 786 845 } while (writtenBytes < 0 && errno == EINTR); 787 846 … … 825 884 ssize_t r = 0; 826 885 do { 886 827 887 r = ::read(socketDescriptor, data, maxSize); 888 889 890 828 891 } while (r == -1 && errno == EINTR); 829 892 … … 843 906 setError(QAbstractSocket::NetworkError, ReadErrorString); 844 907 break; 908 909 910 845 911 case ECONNRESET: 912 913 914 846 915 r = 0; 847 916 break; … … 870 939 tv.tv_usec = (timeout % 1000) * 1000; 871 940 872 QTime timer; 873 timer.start(); 941 #ifdef Q_OS_SYMBIAN 942 fd_set fdexception; 943 FD_ZERO(&fdexception); 944 FD_SET(socketDescriptor, &fdexception); 945 #endif 874 946 875 947 int retval; 876 do { 877 if (selectForRead) 878 retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); 879 else 880 retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); 881 882 if (retval != -1 || errno != EINTR) 883 break; 884 885 if (timeout > 0) { 886 // recalculate the timeout 887 int t = timeout - timer.elapsed(); 888 if (t < 0) { 889 // oops, timeout turned negative? 890 retval = -1; 891 break; 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); 892 967 } 893 894 tv.tv_sec = t / 1000; 895 tv.tv_usec = (t % 1000) * 1000; 896 } 897 } while (true); 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 898 975 899 976 return retval; … … 901 978 902 979 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, 903 980 bool *selectForRead, bool *selectForWrite) const 904 981 { 905 982 fd_set fdread; … … 913 990 FD_SET(socketDescriptor, &fdwrite); 914 991 992 993 994 995 996 997 915 998 struct timeval tv; 916 999 tv.tv_sec = timeout / 1000; 917 1000 tv.tv_usec = (timeout % 1000) * 1000; 918 1001 1002 1003 1004 1005 919 1006 QTime timer; 920 1007 timer.start(); 921 1008 922 int ret;923 1009 do { 924 ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); 925 if (ret != -1 || errno != EINTR) 926 break; 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 } 927 1036 928 1037 if (timeout > 0) { … … 939 1048 } 940 1049 } while (true); 1050 1051 941 1052 if (ret <= 0) 942 1053 return ret; 943 944 1054 *selectForRead = FD_ISSET(socketDescriptor, &fdread); 945 1055 *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); 1056 946 1057 return ret; 947 1058 }
Note:
See TracChangeset
for help on using the changeset viewer.