summaryrefslogtreecommitdiffstats
path: root/src/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket')
-rw-r--r--src/network/socket/qabstractsocket.cpp68
-rw-r--r--src/network/socket/qabstractsocket.h8
-rw-r--r--src/network/socket/qabstractsocketengine_p.h4
-rw-r--r--src/network/socket/qhttpsocketengine.cpp22
-rw-r--r--src/network/socket/qlocalserver_unix.cpp4
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp4
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp49
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp22
-rw-r--r--src/network/socket/qnet_unix_p.h26
-rw-r--r--src/network/socket/qsocks5socketengine.cpp20
-rw-r--r--src/network/socket/qtcpsocket.cpp8
-rw-r--r--src/network/socket/qtcpsocket.h1
-rw-r--r--src/network/socket/qudpsocket.cpp3
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