summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Goetz <Markus.Goetz@nokia.com>2009-07-22 07:59:54 (GMT)
committerMarkus Goetz <Markus.Goetz@nokia.com>2009-07-23 10:18:38 (GMT)
commitd6a01d0f948361ac5cacab0bf9f8585041485259 (patch)
treef17bc439920c2f366be9528cf41bc45e69209fc3
parent9377881d6d6f5c07aa134c8f1708d0afd0d06e86 (diff)
downloadQt-d6a01d0f948361ac5cacab0bf9f8585041485259.zip
Qt-d6a01d0f948361ac5cacab0bf9f8585041485259.tar.gz
Qt-d6a01d0f948361ac5cacab0bf9f8585041485259.tar.bz2
Sockets: Added support for SO_KEEPALIVE and TCP_NODELAY
Introduce QAbstractSocket::setSocketOption that allows to set the socket options for TCP Keep Alive and TCP_NODELAY (disabling Nagle's Algorithm). Reviewed-by: Thiago
-rw-r--r--src/network/socket/qabstractsocket.cpp64
-rw-r--r--src/network/socket/qabstractsocket.h8
-rw-r--r--src/network/socket/qabstractsocketengine_p.h4
-rw-r--r--src/network/socket/qhttpsocketengine.cpp21
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp24
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp22
-rw-r--r--src/network/socket/qsocks5socketengine.cpp20
-rw-r--r--src/network/socket/qtcpsocket.h1
8 files changed, 154 insertions, 10 deletions
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index d099382..be90b96 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -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,54 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock
return true;
}
+/*!
+ Sets the option \a option to the value described by \a value.
+
+ \sa socketOption()
+*/
+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()
+*/
+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 ed187e5..50a38bb 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 b784f65..39c00cc 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 156a9f4..84b7c14 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;
}
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 3991ae6..b4b673a 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;
@@ -282,9 +295,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)
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 6bc23ce..f0b9f0b 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/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index c9e5150..d226f21 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.h b/src/network/socket/qtcpsocket.h
index 81f81de..4e1003a 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