diff options
Diffstat (limited to 'src/network/socket')
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 68 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket.h | 8 | ||||
-rw-r--r-- | src/network/socket/qabstractsocketengine_p.h | 4 | ||||
-rw-r--r-- | src/network/socket/qhttpsocketengine.cpp | 22 | ||||
-rw-r--r-- | src/network/socket/qlocalserver_unix.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qlocalsocket_unix.cpp | 4 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_p.h | 4 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 49 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 22 | ||||
-rw-r--r-- | src/network/socket/qnet_unix_p.h | 26 | ||||
-rw-r--r-- | src/network/socket/qsocks5socketengine.cpp | 20 | ||||
-rw-r--r-- | src/network/socket/qtcpsocket.cpp | 8 | ||||
-rw-r--r-- | src/network/socket/qtcpsocket.h | 1 | ||||
-rw-r--r-- | src/network/socket/qudpsocket.cpp | 3 |
14 files changed, 216 insertions, 27 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index d099382a6..c8ddce001 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -160,7 +160,7 @@ issue to be aware of, though: You must make sure that enough data is available before attempting to read it using operator>>(). - \sa QFtp, QHttp, QTcpServer + \sa QFtp, QNetworkAccessManager, QTcpServer */ /*! @@ -332,6 +332,22 @@ \sa QAbstractSocket::state() */ +/*! + \enum QAbstractSocket::SocketOption + \since 4.6 + + This enum represents the options that can be set on a socket. + If desired, they can be set after having received the connected() signal from + the socket or after having received a new socket from a QTcpServer. + + \value LowDelayOption Try to optimize the socket for low latency. For a QTcpSocket + this would set the TCP_NODELAY option and disable Nagle's algorithm. Set this to 1 + to enable. + \value KeepAliveOption Set this to 1 to enable the SO_KEEPALIVE socket option + + \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption() +*/ + #include "qabstractsocket.h" #include "qabstractsocket_p.h" @@ -1548,6 +1564,56 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock return true; } +/*! + Sets the option \a option to the value described by \a value. + + \sa socketOption() + \since 4.6 +*/ +void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, QVariant value) +{ + if (!d_func()->socketEngine) + return; + + switch (option) { + case LowDelayOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::LowDelayOption, value.toInt()); + break; + + case KeepAliveOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt()); + break; + } +} + +/*! + Returns the value of the \a option option. + + \sa setSocketOption() + \since 4.6 +*/ +QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) +{ + if (!d_func()->socketEngine) + return QVariant(); + + int ret = -1; + switch (option) { + case LowDelayOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::LowDelayOption); + break; + + case KeepAliveOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption); + break; + } + if (ret == -1) + return QVariant(); + else + return QVariant(ret); +} + + /* Returns the difference between msecs and elapsed. If msecs is -1, however, -1 is returned. diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index ed187e54e..50a38bb7a 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -116,6 +116,10 @@ public: Connection = ConnectedState #endif }; + enum SocketOption { + LowDelayOption, // TCP_NODELAY + KeepAliveOption // SO_KEEPALIVE + }; QAbstractSocket(SocketType socketType, QObject *parent); virtual ~QAbstractSocket(); @@ -149,6 +153,10 @@ public: bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState, OpenMode openMode = ReadWrite); + // ### Qt 5: Make virtual? + void setSocketOption(QAbstractSocket::SocketOption o, QVariant v); + QVariant socketOption(QAbstractSocket::SocketOption o); + SocketType socketType() const; SocketState state() const; SocketError error() const; diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index b784f6585..39c00cc15 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -92,7 +92,9 @@ public: SendBufferSocketOption, AddressReusable, BindExclusively, - ReceiveOutOfBandData + ReceiveOutOfBandData, + LowDelayOption, + KeepAliveOption }; virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 7bac1f271..84b7c1403 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -276,13 +276,30 @@ qint64 QHttpSocketEngine::pendingDatagramSize() const } #endif // QT_NO_UDPSOCKET -int QHttpSocketEngine::option(SocketOption) const +int QHttpSocketEngine::option(SocketOption option) const { + Q_D(const QHttpSocketEngine); + if (d->socket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + return d->socket->socketOption(QAbstractSocket::LowDelayOption).toInt(); + if (option == QAbstractSocketEngine::KeepAliveOption) + return d->socket->socketOption(QAbstractSocket::KeepAliveOption).toInt(); + } return -1; } -bool QHttpSocketEngine::setOption(SocketOption, int) +bool QHttpSocketEngine::setOption(SocketOption option, int value) { + Q_D(QHttpSocketEngine); + if (d->socket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + d->socket->setSocketOption(QAbstractSocket::LowDelayOption, value); + if (option == QAbstractSocketEngine::KeepAliveOption) + d->socket->setSocketOption(QAbstractSocket::KeepAliveOption, value); + return true; + } return false; } @@ -454,6 +471,7 @@ void QHttpSocketEngine::slotSocketConnected() data += path; data += " HTTP/1.1\r\n"; data += "Proxy-Connection: keep-alive\r\n" + "User-Agent: Mozilla/5.0\r\n" "Host: " + peerAddress + "\r\n"; QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator); //qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1); diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index c2e05cdfd..3df6b6aa4 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -54,6 +54,10 @@ #include <qdir.h> #include <qdatetime.h> +#ifdef Q_OS_VXWORKS +# include <selectLib.h> +#endif + QT_BEGIN_NAMESPACE void QLocalServerPrivate::init() diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index d038794e2..08d94efa5 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -56,6 +56,10 @@ #include <qdir.h> #include <qdebug.h> +#ifdef Q_OS_VXWORKS +# include <selectLib.h> +#endif + #define QT_CONNECT_TIMEOUT 30000 QT_BEGIN_NAMESPACE diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index a9479d31d..24dc34448 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -56,9 +56,9 @@ #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" #ifndef Q_OS_WIN -# include "qplatformdefs.h" +# include "qplatformdefs.h" #else -# include <winsock2.h> +# include <winsock2.h> #endif QT_BEGIN_NAMESPACE diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 3991ae61c..6f9ee1afb 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -65,6 +65,8 @@ #include <ctype.h> #endif +#include <netinet/tcp.h> + QT_BEGIN_NAMESPACE #if defined QNATIVESOCKETENGINE_DEBUG @@ -203,6 +205,8 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co return -1; int n = -1; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -222,11 +226,18 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) + if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; return -1; } @@ -242,6 +253,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return false; int n = 0; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -254,6 +267,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt break; case QNativeSocketEngine::NonBlockingSocketOption: { // Make the socket nonblocking. +#if !defined(Q_OS_VXWORKS) int flags = ::fcntl(socketDescriptor, F_GETFL, 0); if (flags == -1) { #ifdef QNATIVESOCKETENGINE_DEBUG @@ -267,7 +281,15 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt #endif return false; } - +#else // Q_OS_VXWORKS + int onoff = 1; + if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) { +#ifdef QNATIVESOCKETENGINE_DEBUG + perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed"); +#endif + return false; + } +#endif // Q_OS_VXWORKS return true; } case QNativeSocketEngine::AddressReusable: @@ -282,9 +304,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } - return ::setsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, sizeof(v)) == 0; + return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; } bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port) @@ -632,11 +661,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l // ignore the SIGPIPE signal qt_ignore_sigpipe(); - ssize_t sentBytes; - do { - sentBytes = qt_safe_sendto(socketDescriptor, data, len, - 0, sockAddrPtr, sockAddrSize); - } while (sentBytes == -1 && errno == EINTR); + ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, + 0, sockAddrPtr, sockAddrSize); if (sentBytes < 0) { switch (errno) { @@ -702,7 +728,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() // Determine the socket type (UDP/TCP) int value = 0; QT_SOCKOPTLEN_T valueSize = sizeof(int); - if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) { + if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) == 0) { if (value == SOCK_STREAM) socketType = QAbstractSocket::TcpSocket; else if (value == SOCK_DGRAM) @@ -747,7 +773,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) // of an interrupting signal. ssize_t writtenBytes; do { - writtenBytes = ::write(socketDescriptor, data, len); + writtenBytes = QT_WRITE(socketDescriptor, data, len); } while (writtenBytes < 0 && errno == EINTR); if (writtenBytes < 0) { @@ -808,6 +834,9 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) setError(QAbstractSocket::NetworkError, ReadErrorString); break; case ECONNRESET: +#if defined(Q_OS_VXWORKS) + case ESHUTDOWN: +#endif r = 0; break; default: diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 6bc23ceb7..f0b9f0bd9 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -362,6 +362,8 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co return -1; int n = -1; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -389,11 +391,18 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } int v = -1; QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, SOL_SOCKET, n, (char *) &v, &len) != -1) + if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; return -1; } @@ -409,6 +418,8 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt return false; int n = 0; + int level = SOL_SOCKET; // default + switch (opt) { case QNativeSocketEngine::ReceiveBufferSocketOption: n = SO_RCVBUF; @@ -440,9 +451,16 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::ReceiveOutOfBandData: n = SO_OOBINLINE; break; + case QNativeSocketEngine::LowDelayOption: + level = IPPROTO_TCP; + n = TCP_NODELAY; + break; + case QNativeSocketEngine::KeepAliveOption: + n = SO_KEEPALIVE; + break; } - if (::setsockopt(socketDescriptor, SOL_SOCKET, n, (char*)&v, sizeof(v)) != 0) { + if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) { WS_ERROR_DEBUG(WSAGetLastError()); return false; } diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h index 03ed3b4c9..f38c2fcfa 100644 --- a/src/network/socket/qnet_unix_p.h +++ b/src/network/socket/qnet_unix_p.h @@ -59,11 +59,18 @@ #include <sys/socket.h> #include <netinet/in.h> +#if defined(Q_OS_VXWORKS) +# include <sockLib.h> +#endif + // for inet_addr #include <netdb.h> #include <arpa/inet.h> -#include <resolv.h> - +#if defined(Q_OS_VXWORKS) +# include <hostLib.h> +#else +# include <resolv.h> +#endif QT_BEGIN_NAMESPACE @@ -155,17 +162,28 @@ static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SO # undef listen #endif +// VxWorks' headers specify 'int' instead of '...' for the 3rd ioctl() parameter. template <typename T> static inline int qt_safe_ioctl(int sockfd, int request, T arg) { +#ifdef Q_OS_VXWORKS + return ::ioctl(sockfd, request, (int) arg); +#else return ::ioctl(sockfd, request, arg); +#endif } +// VxWorks' headers do not specify any const modifiers static inline in_addr_t qt_safe_inet_addr(const char *cp) { +#ifdef Q_OS_VXWORKS + return ::inet_addr((char *) cp); +#else return ::inet_addr(cp); +#endif } +// VxWorks' headers do not specify any const modifiers static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *to, QT_SOCKLEN_T tolen) { #ifdef MSG_NOSIGNAL @@ -173,7 +191,11 @@ static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int fl #endif register int ret; +#ifdef Q_OS_VXWORKS + EINTR_LOOP(ret, ::sendto(sockfd, (char *) buf, len, flags, (struct sockaddr *) to, tolen)); +#else EINTR_LOOP(ret, ::sendto(sockfd, buf, len, flags, to, tolen)); +#endif return ret; } diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index c9e515089..d226f21da 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -1621,14 +1621,28 @@ qint64 QSocks5SocketEngine::pendingDatagramSize() const int QSocks5SocketEngine::option(SocketOption option) const { - Q_UNUSED(option); + Q_D(const QSocks5SocketEngine); + if (d->data && d->data->controlSocket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + return d->data->controlSocket->socketOption(QAbstractSocket::LowDelayOption).toInt(); + if (option == QAbstractSocketEngine::KeepAliveOption) + return d->data->controlSocket->socketOption(QAbstractSocket::KeepAliveOption).toInt(); + } return -1; } bool QSocks5SocketEngine::setOption(SocketOption option, int value) { - Q_UNUSED(option); - Q_UNUSED(value); + Q_D(QSocks5SocketEngine); + if (d->data && d->data->controlSocket) { + // convert the enum and call the real socket + if (option == QAbstractSocketEngine::LowDelayOption) + d->data->controlSocket->setSocketOption(QAbstractSocket::LowDelayOption, value); + if (option == QAbstractSocketEngine::KeepAliveOption) + d->data->controlSocket->setSocketOption(QAbstractSocket::KeepAliveOption, value); + return true; + } return false; } diff --git a/src/network/socket/qtcpsocket.cpp b/src/network/socket/qtcpsocket.cpp index dc0439d13..60722cce1 100644 --- a/src/network/socket/qtcpsocket.cpp +++ b/src/network/socket/qtcpsocket.cpp @@ -60,10 +60,10 @@ \bold{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode. - \sa QTcpServer, QUdpSocket, QFtp, QHttp, {Fortune Server Example}, - {Fortune Client Example}, {Threaded Fortune Server Example}, - {Blocking Fortune Client Example}, {Loopback Example}, - {Torrent Example} + \sa QTcpServer, QUdpSocket, QFtp, QNetworkAccessManager, + {Fortune Server Example}, {Fortune Client Example}, + {Threaded Fortune Server Example}, {Blocking Fortune Client Example}, + {Loopback Example}, {Torrent Example} */ #include "qlist.h" diff --git a/src/network/socket/qtcpsocket.h b/src/network/socket/qtcpsocket.h index 81f81dea9..4e1003ab7 100644 --- a/src/network/socket/qtcpsocket.h +++ b/src/network/socket/qtcpsocket.h @@ -43,6 +43,7 @@ #define QTCPSOCKET_H #include <QtNetwork/qabstractsocket.h> +#include <QtCore/qvariant.h> QT_BEGIN_HEADER diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index ea7753cdb..797becb78 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -70,6 +70,9 @@ pendingDatagramSize() to obtain the size of the first pending datagram, and readDatagram() to read it. + \note An incoming datagram should be read when you receive the readyRead() + signal, otherwise this signal will not be emitted for the next datagram. + Example: \snippet doc/src/snippets/code/src_network_socket_qudpsocket.cpp 0 |