summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/access.pri7
-rw-r--r--src/network/access/qabstractnetworkcache.cpp12
-rw-r--r--src/network/access/qabstractnetworkcache.h8
-rw-r--r--src/network/access/qabstractnetworkcache_p.h8
-rw-r--r--src/network/access/qftp.cpp33
-rw-r--r--src/network/access/qftp.h8
-rw-r--r--src/network/access/qhttp.cpp54
-rw-r--r--src/network/access/qhttp.h11
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp1080
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h130
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp884
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h192
-rw-r--r--src/network/access/qhttpnetworkheader.cpp8
-rw-r--r--src/network/access/qhttpnetworkheader_p.h8
-rw-r--r--src/network/access/qhttpnetworkreply.cpp217
-rw-r--r--src/network/access/qhttpnetworkreply_p.h46
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp44
-rw-r--r--src/network/access/qhttpnetworkrequest_p.h22
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp77
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h50
-rw-r--r--src/network/access/qnetworkaccesscache.cpp8
-rw-r--r--src/network/access/qnetworkaccesscache_p.h11
-rw-r--r--src/network/access/qnetworkaccesscachebackend.cpp9
-rw-r--r--src/network/access/qnetworkaccesscachebackend_p.h8
-rw-r--r--src/network/access/qnetworkaccessdatabackend.cpp14
-rw-r--r--src/network/access/qnetworkaccessdatabackend_p.h8
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend.cpp296
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend_p.h31
-rw-r--r--src/network/access/qnetworkaccessfilebackend.cpp101
-rw-r--r--src/network/access/qnetworkaccessfilebackend_p.h17
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp96
-rw-r--r--src/network/access/qnetworkaccessftpbackend_p.h17
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp190
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h27
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp131
-rw-r--r--src/network/access/qnetworkaccessmanager.h10
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h20
-rw-r--r--src/network/access/qnetworkcookie.cpp272
-rw-r--r--src/network/access/qnetworkcookie.h31
-rw-r--r--src/network/access/qnetworkcookie_p.h8
-rw-r--r--src/network/access/qnetworkcookiejar.cpp296
-rw-r--r--src/network/access/qnetworkcookiejar.h81
-rw-r--r--src/network/access/qnetworkcookiejar_p.h71
-rw-r--r--src/network/access/qnetworkdiskcache.cpp68
-rw-r--r--src/network/access/qnetworkdiskcache.h13
-rw-r--r--src/network/access/qnetworkdiskcache_p.h8
-rw-r--r--src/network/access/qnetworkreply.cpp71
-rw-r--r--src/network/access/qnetworkreply.h12
-rw-r--r--src/network/access/qnetworkreply_p.h10
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp266
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h32
-rw-r--r--src/network/access/qnetworkrequest.cpp30
-rw-r--r--src/network/access/qnetworkrequest.h11
-rw-r--r--src/network/access/qnetworkrequest_p.h8
-rw-r--r--src/network/kernel/kernel.pri5
-rw-r--r--src/network/kernel/qauthenticator.cpp19
-rw-r--r--src/network/kernel/qauthenticator.h8
-rw-r--r--src/network/kernel/qauthenticator_p.h8
-rw-r--r--src/network/kernel/qhostaddress.cpp17
-rw-r--r--src/network/kernel/qhostaddress.h11
-rw-r--r--src/network/kernel/qhostaddress_p.h8
-rw-r--r--src/network/kernel/qhostinfo.cpp43
-rw-r--r--src/network/kernel/qhostinfo.h11
-rw-r--r--src/network/kernel/qhostinfo_p.h13
-rw-r--r--src/network/kernel/qhostinfo_unix.cpp52
-rw-r--r--src/network/kernel/qhostinfo_win.cpp30
-rw-r--r--src/network/kernel/qnetworkinterface.cpp26
-rw-r--r--src/network/kernel/qnetworkinterface.h11
-rw-r--r--src/network/kernel/qnetworkinterface_p.h8
-rw-r--r--src/network/kernel/qnetworkinterface_symbian.cpp238
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp27
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp34
-rw-r--r--src/network/kernel/qnetworkinterface_win_p.h10
-rw-r--r--src/network/kernel/qnetworkproxy.cpp49
-rw-r--r--src/network/kernel/qnetworkproxy.h9
-rw-r--r--src/network/kernel/qnetworkproxy_generic.cpp8
-rw-r--r--src/network/kernel/qnetworkproxy_mac.cpp8
-rw-r--r--src/network/kernel/qnetworkproxy_p.h85
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp32
-rw-r--r--src/network/kernel/qurlinfo.cpp10
-rw-r--r--src/network/kernel/qurlinfo.h8
-rw-r--r--src/network/network.pro13
-rw-r--r--src/network/socket/qabstractsocket.cpp98
-rw-r--r--src/network/socket/qabstractsocket.h16
-rw-r--r--src/network/socket/qabstractsocket_p.h10
-rw-r--r--src/network/socket/qabstractsocketengine.cpp8
-rw-r--r--src/network/socket/qabstractsocketengine_p.h12
-rw-r--r--src/network/socket/qhttpsocketengine.cpp30
-rw-r--r--src/network/socket/qhttpsocketengine_p.h8
-rw-r--r--src/network/socket/qlocalserver.cpp22
-rw-r--r--src/network/socket/qlocalserver.h16
-rw-r--r--src/network/socket/qlocalserver_p.h69
-rw-r--r--src/network/socket/qlocalserver_tcp.cpp8
-rw-r--r--src/network/socket/qlocalserver_unix.cpp45
-rw-r--r--src/network/socket/qlocalserver_win.cpp242
-rw-r--r--src/network/socket/qlocalsocket.cpp41
-rw-r--r--src/network/socket/qlocalsocket.h9
-rw-r--r--src/network/socket/qlocalsocket_p.h61
-rw-r--r--src/network/socket/qlocalsocket_tcp.cpp8
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp37
-rw-r--r--src/network/socket/qlocalsocket_win.cpp313
-rw-r--r--src/network/socket/qnativesocketengine.cpp36
-rw-r--r--src/network/socket/qnativesocketengine_p.h45
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp279
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp161
-rw-r--r--src/network/socket/qnet_unix_p.h204
-rw-r--r--src/network/socket/qsocks5socketengine.cpp50
-rw-r--r--src/network/socket/qsocks5socketengine_p.h8
-rw-r--r--src/network/socket/qtcpserver.cpp17
-rw-r--r--src/network/socket/qtcpserver.h8
-rw-r--r--src/network/socket/qtcpsocket.cpp18
-rw-r--r--src/network/socket/qtcpsocket.h9
-rw-r--r--src/network/socket/qtcpsocket_p.h8
-rw-r--r--src/network/socket/qudpsocket.cpp32
-rw-r--r--src/network/socket/qudpsocket.h8
-rw-r--r--src/network/socket/socket.pri5
-rw-r--r--src/network/ssl/qssl.cpp11
-rw-r--r--src/network/ssl/qssl.h8
-rw-r--r--src/network/ssl/qsslcertificate.cpp73
-rw-r--r--src/network/ssl/qsslcertificate.h11
-rw-r--r--src/network/ssl/qsslcertificate_p.h9
-rw-r--r--src/network/ssl/qsslcipher.cpp17
-rw-r--r--src/network/ssl/qsslcipher.h11
-rw-r--r--src/network/ssl/qsslcipher_p.h8
-rw-r--r--src/network/ssl/qsslconfiguration.cpp10
-rw-r--r--src/network/ssl/qsslconfiguration.h8
-rw-r--r--src/network/ssl/qsslconfiguration_p.h8
-rw-r--r--src/network/ssl/qsslerror.cpp43
-rw-r--r--src/network/ssl/qsslerror.h18
-rw-r--r--src/network/ssl/qsslkey.cpp22
-rw-r--r--src/network/ssl/qsslkey.h13
-rw-r--r--src/network/ssl/qsslkey_p.h12
-rw-r--r--src/network/ssl/qsslsocket.cpp104
-rw-r--r--src/network/ssl/qsslsocket.h10
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp46
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h14
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp157
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h10
-rw-r--r--src/network/ssl/qsslsocket_p.h15
-rw-r--r--src/network/ssl/ssl.pri10
140 files changed, 5304 insertions, 3267 deletions
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 3269b2e..edc1b63 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -6,6 +6,7 @@ HEADERS += access/qftp.h \
access/qhttpnetworkrequest_p.h \
access/qhttpnetworkreply_p.h \
access/qhttpnetworkconnection_p.h \
+ access/qhttpnetworkconnectionchannel_p.h \
access/qnetworkaccessmanager.h \
access/qnetworkaccessmanager_p.h \
access/qnetworkaccesscache_p.h \
@@ -18,6 +19,8 @@ HEADERS += access/qftp.h \
access/qnetworkaccessftpbackend_p.h \
access/qnetworkcookie.h \
access/qnetworkcookie_p.h \
+ access/qnetworkcookiejar.h \
+ access/qnetworkcookiejar_p.h \
access/qnetworkrequest.h \
access/qnetworkrequest_p.h \
access/qnetworkreply.h \
@@ -34,6 +37,7 @@ SOURCES += access/qftp.cpp \
access/qhttpnetworkrequest.cpp \
access/qhttpnetworkreply.cpp \
access/qhttpnetworkconnection.cpp \
+ access/qhttpnetworkconnectionchannel.cpp \
access/qnetworkaccessmanager.cpp \
access/qnetworkaccesscache.cpp \
access/qnetworkaccessbackend.cpp \
@@ -44,6 +48,7 @@ SOURCES += access/qftp.cpp \
access/qnetworkaccessftpbackend.cpp \
access/qnetworkaccesshttpbackend.cpp \
access/qnetworkcookie.cpp \
+ access/qnetworkcookiejar.cpp \
access/qnetworkrequest.cpp \
access/qnetworkreply.cpp \
access/qnetworkreplyimpl.cpp \
@@ -54,6 +59,6 @@ SOURCES += access/qftp.cpp \
contains(QT_CONFIG, zlib) {
INCLUDEPATH += ../3rdparty/zlib
} else:!contains(QT_CONFIG, no-zlib) {
- unix:LIBS += -lz
+ unix:LIBS_PRIVATE += -lz
# win32:LIBS += libz.lib
}
diff --git a/src/network/access/qabstractnetworkcache.cpp b/src/network/access/qabstractnetworkcache.cpp
index 5195e8b..5dfc79c 100644
--- a/src/network/access/qabstractnetworkcache.cpp
+++ b/src/network/access/qabstractnetworkcache.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -283,6 +283,8 @@ void QNetworkCacheMetaData::setExpirationDate(const QDateTime &dateTime)
}
/*!
+ \since 4.6
+
Returns all the attributes stored with this cache item.
\sa setAttributes(), QNetworkRequest::Attribute
@@ -293,6 +295,8 @@ QNetworkCacheMetaData::AttributesMap QNetworkCacheMetaData::attributes() const
}
/*!
+ \since 4.6
+
Sets all attributes of this cache item to be the map \a attributes.
\sa attributes(), QNetworkRequest::setAttribute()
diff --git a/src/network/access/qabstractnetworkcache.h b/src/network/access/qabstractnetworkcache.h
index faab1a8..cfebf51 100644
--- a/src/network/access/qabstractnetworkcache.h
+++ b/src/network/access/qabstractnetworkcache.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qabstractnetworkcache_p.h b/src/network/access/qabstractnetworkcache_p.h
index 31906db..2b8f1b0 100644
--- a/src/network/access/qabstractnetworkcache_p.h
+++ b/src/network/access/qabstractnetworkcache_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index cde5a05..08cd9e1 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -314,8 +314,10 @@ void QFtpDTP::connectToHost(const QString & host, quint16 port)
{
bytesFromSocket.clear();
- if (socket)
+ if (socket) {
delete socket;
+ socket = 0;
+ }
socket = new QTcpSocket(this);
socket->setObjectName(QLatin1String("QFtpDTP Passive state socket"));
connect(socket, SIGNAL(connected()), SLOT(socketConnected()));
@@ -869,6 +871,9 @@ void QFtpPI::connected()
#if defined(QFTPPI_DEBUG)
// qDebug("QFtpPI state: %d [connected()]", state);
#endif
+ // try to improve performance by setting TCP_NODELAY
+ commandSocket.setSocketOption(QAbstractSocket::LowDelayOption, 1);
+
emit connectState(QFtp::Connected);
}
@@ -1291,9 +1296,9 @@ int QFtpPrivate::addCommand(QFtpCommand *cmd)
\class QFtp
\brief The QFtp class provides an implementation of the client side of FTP protocol.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
- \mainclass
+
This class provides a direct interface to FTP that allows you to
have more control over the requests. However, for new
@@ -1385,7 +1390,7 @@ int QFtpPrivate::addCommand(QFtpCommand *cmd)
\warning The current version of QFtp doesn't fully support
non-Unix FTP servers.
- \sa QHttp, QNetworkAccessManager, QNetworkRequest, QNetworkReply,
+ \sa QNetworkAccessManager, QNetworkRequest, QNetworkReply,
{FTP Example}
*/
@@ -1658,11 +1663,12 @@ QFtp::QFtp(QObject *parent, const char *name)
*/
int QFtp::connectToHost(const QString &host, quint16 port)
{
- d_func()->pi.transferConnectionExtended = true;
QStringList cmds;
cmds << host;
cmds << QString::number((uint)port);
- return d_func()->addCommand(new QFtpCommand(ConnectToHost, cmds));
+ int id = d_func()->addCommand(new QFtpCommand(ConnectToHost, cmds));
+ d_func()->pi.transferConnectionExtended = true;
+ return id;
}
/*!
@@ -1721,17 +1727,18 @@ int QFtp::close()
*/
int QFtp::setTransferMode(TransferMode mode)
{
+ int id = d_func()->addCommand(new QFtpCommand(SetTransferMode, QStringList()));
d_func()->pi.transferConnectionExtended = true;
d_func()->transferMode = mode;
- return d_func()->addCommand(new QFtpCommand(SetTransferMode, QStringList()));
+ return id;
}
/*!
Enables use of the FTP proxy on host \a host and port \a
port. Calling this function with \a host empty disables proxying.
- QFtp does not support FTP-over-HTTP proxy servers. Use QHttp for
- this.
+ QFtp does not support FTP-over-HTTP proxy servers. Use
+ QNetworkAccessManager for this.
*/
int QFtp::setProxy(const QString &host, quint16 port)
{
diff --git a/src/network/access/qftp.h b/src/network/access/qftp.h
index af8b4c0..bb12fff 100644
--- a/src/network/access/qftp.h
+++ b/src/network/access/qftp.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qhttp.cpp b/src/network/access/qhttp.cpp
index 5ad304c..7d16aa9 100644
--- a/src/network/access/qhttp.cpp
+++ b/src/network/access/qhttp.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -513,9 +513,10 @@ public:
/*!
\class QHttpHeader
+ \obsolete
\brief The QHttpHeader class contains header information for HTTP.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
In most cases you should use the more specialized derivatives of
@@ -624,7 +625,6 @@ QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header)
*/
QHttpHeader::~QHttpHeader()
{
- delete d_ptr;
}
/*!
@@ -1007,9 +1007,10 @@ public:
/*!
\class QHttpResponseHeader
+ \obsolete
\brief The QHttpResponseHeader class contains response header information for HTTP.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
This class is used by the QHttp class to report the header
@@ -1152,7 +1153,7 @@ int QHttpResponseHeader::minorVersion() const
return d->minVer;
}
-/*! \reimp
+/*! \internal
*/
bool QHttpResponseHeader::parseLine(const QString &line, int number)
{
@@ -1211,9 +1212,10 @@ public:
/*!
\class QHttpRequestHeader
+ \obsolete
\brief The QHttpRequestHeader class contains request header information for HTTP.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
This class is used in the QHttp class to report the header
@@ -1366,7 +1368,7 @@ int QHttpRequestHeader::minorVersion() const
return d->minVer;
}
-/*! \reimp
+/*! \internal
*/
bool QHttpRequestHeader::parseLine(const QString &line, int number)
{
@@ -1413,19 +1415,21 @@ QString QHttpRequestHeader::toString() const
****************************************************/
/*!
\class QHttp
+ \obsolete
\reentrant
\brief The QHttp class provides an implementation of the HTTP protocol.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
- \mainclass
+
This class provides a direct interface to HTTP that allows you to
- have more control over the requests and that allows you to access
- the response header fields. However, for new applications, it is
+ download and upload data with the HTTP protocol.
+ However, for new applications, it is
recommended to use QNetworkAccessManager and QNetworkReply, as
- those classes possess a simpler, yet more powerful API.
+ those classes possess a simpler, yet more powerful API
+ and a more modern protocol implementation.
The class works asynchronously, so there are no blocking
functions. If an operation cannot be executed immediately, the
@@ -1446,8 +1450,8 @@ QString QHttpRequestHeader::toString() const
that indicates if the request finished with an error.
To make an HTTP request you must set up suitable HTTP headers. The
- following example demonstrates, how to request the main HTML page
- from the Qt home page (i.e., the URL \c http://qt.nokia.com/index.html):
+ following example demonstrates how to request the main HTML page
+ from the Qt website (i.e., the URL \c http://qt.nokia.com/index.html):
\snippet doc/src/snippets/code/src_network_access_qhttp.cpp 2
@@ -1591,11 +1595,11 @@ QHttp::~QHttp()
This enum is used to specify the mode of connection to use:
- \value ConnectionModeHttp The connection is a regular Http connection to the server
- \value ConnectionModeHttps The Https protocol is used and the connection is encrypted using SSL.
+ \value ConnectionModeHttp The connection is a regular HTTP connection to the server
+ \value ConnectionModeHttps The HTTPS protocol is used and the connection is encrypted using SSL.
- When using the Https mode, care should be taken to connect to the sslErrors signal, and
- handle possible Ssl errors.
+ When using the HTTPS mode, care should be taken to connect to the sslErrors signal, and
+ handle possible SSL errors.
\sa QSslSocket
*/
@@ -2033,7 +2037,7 @@ int QHttp::setHost(const QString &hostName, quint16 port)
port \a port using the connection mode \a mode.
If port is 0, it will use the default port for the \a mode used
- (80 for Http and 443 fopr Https).
+ (80 for HTTP and 443 for HTTPS).
The function does not block; instead, it returns immediately. The request
is scheduled, and its execution is performed asynchronously. The
@@ -2160,7 +2164,7 @@ int QHttp::setProxy(const QNetworkProxy &proxy)
as specified in the constructor.
\a path must be a absolute path like \c /index.html or an
- absolute URI like \c http://qt.nokia.com/index.html and
+ absolute URI like \c http://example.com/index.html and
must be encoded with either QUrl::toPercentEncoding() or
QUrl::encodedPath().
@@ -2199,7 +2203,7 @@ int QHttp::get(const QString &path, QIODevice *to)
as specified in the constructor.
\a path must be an absolute path like \c /index.html or an
- absolute URI like \c http://qt.nokia.com/index.html and
+ absolute URI like \c http://example.com/index.html and
must be encoded with either QUrl::toPercentEncoding() or
QUrl::encodedPath().
@@ -2250,7 +2254,7 @@ int QHttp::post(const QString &path, const QByteArray &data, QIODevice *to)
or as specified in the constructor.
\a path must be an absolute path like \c /index.html or an
- absolute URI like \c http://qt.nokia.com/index.html.
+ absolute URI like \c http://example.com/index.html.
The function does not block; instead, it returns immediately. The request
is scheduled, and its execution is performed asynchronously. The
diff --git a/src/network/access/qhttp.h b/src/network/access/qhttp.h
index 1ba67d6..1483b7d 100644
--- a/src/network/access/qhttp.h
+++ b/src/network/access/qhttp.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,6 +46,7 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qpair.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -108,7 +109,7 @@ protected:
QHttpHeader(QHttpHeaderPrivate &dd, const QString &str = QString());
QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header);
- QHttpHeaderPrivate *d_ptr;
+ QScopedPointer<QHttpHeaderPrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QHttpHeader)
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 4fcbc1f..bd6fa57 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -40,6 +40,8 @@
****************************************************************************/
#include "qhttpnetworkconnection_p.h"
+#include "qhttpnetworkconnectionchannel_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#include <private/qnetworkrequest_p.h>
#include <private/qobject_p.h>
#include <private/qauthenticator_p.h>
@@ -63,70 +65,57 @@
QT_BEGIN_NAMESPACE
-const int QHttpNetworkConnectionPrivate::channelCount = 2;
+#ifdef Q_OS_SYMBIAN
+const int QHttpNetworkConnectionPrivate::defaultChannelCount = 3;
+#else
+const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6;
+#endif
+
+// the maximum amount of requests that might be pipelined into a socket
+// from what was suggested, 3 seems to be OK
+const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3;
+
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
: hostName(hostName), port(port), encrypt(encrypt),
+ channelCount(defaultChannelCount),
pendingAuthSignal(false), pendingProxyAuthSignal(false)
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
{
+ channels = new QHttpNetworkConnectionChannel[channelCount];
}
-QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
+QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt)
+: hostName(hostName), port(port), encrypt(encrypt),
+ channelCount(channelCount),
+ pendingAuthSignal(false), pendingProxyAuthSignal(false)
+#ifndef QT_NO_NETWORKPROXY
+ , networkProxy(QNetworkProxy::NoProxy)
+#endif
{
- for (int i = 0; i < channelCount; ++i) {
- channels[i].socket->close();
- delete channels[i].socket;
- }
+ channels = new QHttpNetworkConnectionChannel[channelCount];
}
-void QHttpNetworkConnectionPrivate::connectSignals(QAbstractSocket *socket)
-{
- Q_Q(QHttpNetworkConnection);
- QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
- q, SLOT(_q_bytesWritten(qint64)),
- Qt::DirectConnection);
- QObject::connect(socket, SIGNAL(connected()),
- q, SLOT(_q_connected()),
- Qt::DirectConnection);
- QObject::connect(socket, SIGNAL(readyRead()),
- q, SLOT(_q_readyRead()),
- Qt::DirectConnection);
- QObject::connect(socket, SIGNAL(disconnected()),
- q, SLOT(_q_disconnected()),
- Qt::DirectConnection);
- QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
- q, SLOT(_q_error(QAbstractSocket::SocketError)),
- Qt::DirectConnection);
-#ifndef QT_NO_NETWORKPROXY
- QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
- q, SLOT(_q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
- Qt::DirectConnection);
-#endif
-#ifndef QT_NO_OPENSSL
- QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
- QObject::connect(sslSocket, SIGNAL(encrypted()),
- q, SLOT(_q_encrypted()),
- Qt::DirectConnection);
- QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError>&)),
- q, SLOT(_q_sslErrors(const QList<QSslError>&)),
- Qt::DirectConnection);
-#endif
+QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
+{
+ for (int i = 0; i < channelCount; ++i) {
+ if (channels[i].socket) {
+ channels[i].socket->close();
+ delete channels[i].socket;
+ }
+ }
+ delete []channels;
}
void QHttpNetworkConnectionPrivate::init()
{
- for (int i = 0; i < channelCount; ++i) {
-#ifndef QT_NO_OPENSSL
- channels[i].socket = new QSslSocket;
-#else
- channels[i].socket = new QTcpSocket;
-#endif
- connectSignals(channels[i].socket);
+ for (int i = 0; i < channelCount; i++) {
+ channels[i].setConnection(this->q_func());
+ channels[i].init();
}
}
@@ -140,63 +129,14 @@ int QHttpNetworkConnectionPrivate::indexOf(QAbstractSocket *socket) const
return 0;
}
-bool QHttpNetworkConnectionPrivate::isSocketBusy(QAbstractSocket *socket) const
-{
- int i = indexOf(socket);
- return (channels[i].state & BusyState);
-}
-
-bool QHttpNetworkConnectionPrivate::isSocketWriting(QAbstractSocket *socket) const
-{
- int i = indexOf(socket);
- return (i != -1 && (channels[i].state & WritingState));
-}
-
-bool QHttpNetworkConnectionPrivate::isSocketWaiting(QAbstractSocket *socket) const
-{
- int i = indexOf(socket);
- return (i != -1 && (channels[i].state & WaitingState));
-}
-
-bool QHttpNetworkConnectionPrivate::isSocketReading(QAbstractSocket *socket) const
-{
- int i = indexOf(socket);
- return (i != -1 && (channels[i].state & ReadingState));
-}
-
-
-void QHttpNetworkConnectionPrivate::appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed)
+qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailable(const QHttpNetworkReply &reply) const
{
- QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
- ba->append(fragment);
- return;
+ return reply.d_func()->responseData.byteAmount();
}
-qint64 QHttpNetworkConnectionPrivate::bytesAvailable(const QHttpNetworkReply &reply, bool compressed) const
+qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const
{
- const QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
- return ba->size();
-}
-
-qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed)
-{
- QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData;
- if (maxSize == -1 || maxSize >= ba->size()) {
- // read the whole data
- data = *ba;
- ba->clear();
- } else {
- // read only the requested length
- data = ba->mid(0, maxSize);
- ba->remove(0, maxSize);
- }
- return data.size();
-}
-
-void QHttpNetworkConnectionPrivate::eraseData(QHttpNetworkReply *reply)
-{
- reply->d_func()->compressedData.clear();
- reply->d_func()->responseData.clear();
+ return reply.d_func()->responseData.sizeNextBlock();
}
void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
@@ -207,12 +147,19 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
// add missing fields for the request
QByteArray value;
// check if Content-Length is provided
- QIODevice *data = request.data();
- if (data && request.contentLength() == -1) {
- if (!data->isSequential())
- request.setContentLength(data->size());
- else
- bufferData(messagePair); // ### or do chunked upload
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (uploadByteDevice) {
+ if (request.contentLength() != -1 && uploadByteDevice->size() != -1) {
+ // both values known, take the smaller one.
+ request.setContentLength(qMin(uploadByteDevice->size(), request.contentLength()));
+ } else if (request.contentLength() == -1 && uploadByteDevice->size() != -1) {
+ // content length not supplied by user, but the upload device knows it
+ request.setContentLength(uploadByteDevice->size());
+ } else if (request.contentLength() != -1 && uploadByteDevice->size() == -1) {
+ // everything OK, the user supplied us the contentLength
+ } else if (request.contentLength() == -1 && uploadByteDevice->size() == -1) {
+ qFatal("QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given");
+ }
}
// set the Connection/Proxy-Connection: Keep-Alive headers
#ifndef QT_NO_NETWORKPROXY
@@ -265,183 +212,8 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
reply->d_func()->requestIsPrepared = true;
}
-bool QHttpNetworkConnectionPrivate::ensureConnection(QAbstractSocket *socket)
-{
- // make sure that this socket is in a connected state, if not initiate
- // connection to the host.
- if (socket->state() != QAbstractSocket::ConnectedState) {
- // connect to the host if not already connected.
- int index = indexOf(socket);
- // resend this request after we receive the disconnected signal
- if (socket->state() == QAbstractSocket::ClosingState) {
- channels[index].resendCurrent = true;
- return false;
- }
- channels[index].state = ConnectingState;
- channels[index].pendingEncrypt = encrypt;
-
- // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done"
- // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the
- // last header for Authorization is generated by the QAuthenticator. Basic & Digest logic does not
- // check the "phase" for generating the Authorization header. NTLM authentication is a two stage
- // process & needs the "phase". To make sure the QAuthenticator uses the current username/password
- // the phase is reset to Start.
- QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[index].authenticator);
- if (priv && priv->phase == QAuthenticatorPrivate::Done)
- priv->phase = QAuthenticatorPrivate::Start;
- priv = QAuthenticatorPrivate::getPrivate(channels[index].proxyAuthenticator);
- if (priv && priv->phase == QAuthenticatorPrivate::Done)
- priv->phase = QAuthenticatorPrivate::Start;
-
- QString connectHost = hostName;
- qint16 connectPort = port;
-
-#ifndef QT_NO_NETWORKPROXY
- // HTTPS always use transparent proxy.
- if (networkProxy.type() != QNetworkProxy::NoProxy && !encrypt) {
- connectHost = networkProxy.hostName();
- connectPort = networkProxy.port();
- }
-#endif
- if (encrypt) {
-#ifndef QT_NO_OPENSSL
- QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
- sslSocket->connectToHostEncrypted(connectHost, connectPort);
- if (channels[index].ignoreSSLErrors)
- sslSocket->ignoreSslErrors();
-#else
- emitReplyError(socket, channels[index].reply, QNetworkReply::ProtocolUnknownError);
-#endif
- } else {
- socket->connectToHost(connectHost, connectPort);
- }
- return false;
- }
- return true;
-}
-bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket)
-{
- Q_Q(QHttpNetworkConnection);
-
- int i = indexOf(socket);
- switch (channels[i].state) {
- case IdleState: { // write the header
- if (!ensureConnection(socket)) {
- // wait for the connection (and encryption) to be done
- // sendRequest will be called again from either
- // _q_connected or _q_encrypted
- return false;
- }
- channels[i].written = 0; // excluding the header
- channels[i].bytesTotal = 0;
- if (channels[i].reply) {
- channels[i].reply->d_func()->clear();
- channels[i].reply->d_func()->connection = q;
- channels[i].reply->d_func()->autoDecompress = channels[i].request.d->autoDecompress;
- }
- channels[i].state = WritingState;
- channels[i].pendingEncrypt = false;
- // if the url contains authentication parameters, use the new ones
- // both channels will use the new authentication parameters
- if (!channels[i].request.url().userInfo().isEmpty()) {
- QUrl url = channels[i].request.url();
- QAuthenticator &auth = channels[i].authenticator;
- if (url.userName() != auth.user()
- || (!url.password().isEmpty() && url.password() != auth.password())) {
- auth.setUser(url.userName());
- auth.setPassword(url.password());
- copyCredentials(i, &auth, false);
- }
- // clear the userinfo, since we use the same request for resending
- // userinfo in url can conflict with the one in the authenticator
- url.setUserInfo(QString());
- channels[i].request.setUrl(url);
- }
- createAuthorization(socket, channels[i].request);
-#ifndef QT_NO_NETWORKPROXY
- QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request,
- (networkProxy.type() != QNetworkProxy::NoProxy));
-#else
- QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request,
- false);
-#endif
- socket->write(header);
- QIODevice *data = channels[i].request.d->data;
- QHttpNetworkReply *reply = channels[i].reply;
- if (reply && reply->d_func()->requestDataBuffer.size())
- data = &channels[i].reply->d_func()->requestDataBuffer;
- if (data && (data->isOpen() || data->open(QIODevice::ReadOnly))) {
- if (data->isSequential()) {
- channels[i].bytesTotal = -1;
- QObject::connect(data, SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadNoBuffer()));
- QObject::connect(data, SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadNoBuffer()));
- } else {
- channels[i].bytesTotal = data->size();
- }
- } else {
- channels[i].state = WaitingState;
- break;
- }
- // write the initial chunk together with the headers
- // fall through
- }
- case WritingState: { // write the data
- QIODevice *data = channels[i].request.d->data;
- if (channels[i].reply->d_func()->requestDataBuffer.size())
- data = &channels[i].reply->d_func()->requestDataBuffer;
- if (!data || channels[i].bytesTotal == channels[i].written) {
- channels[i].state = WaitingState; // now wait for response
- break;
- }
-
- QByteArray chunk;
- chunk.resize(ChunkSize);
- qint64 readSize = data->read(chunk.data(), ChunkSize);
- if (readSize == -1) {
- // source has reached EOF
- channels[i].state = WaitingState; // now wait for response
- } else if (readSize > 0) {
- // source gave us something useful
- channels[i].written += socket->write(chunk.data(), readSize);
- if (channels[i].reply)
- emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal);
- }
- break;
- }
- case WaitingState:
- case ReadingState:
- case Wait4AuthState:
- // ignore _q_bytesWritten in these states
- // fall through
- default:
- break;
- }
- return true;
-}
-
-bool QHttpNetworkConnectionPrivate::emitSignals(QHttpNetworkReply *reply)
-{
- // for 401 & 407 don't emit the data signals. Content along with these
- // responses are send only if the authentication fails.
- return (reply && reply->d_func()->statusCode != 401 && reply->d_func()->statusCode != 407);
-}
-
-bool QHttpNetworkConnectionPrivate::expectContent(QHttpNetworkReply *reply)
-{
- // check whether we can expect content after the headers (rfc 2616, sec4.4)
- if (!reply)
- return false;
- if ((reply->d_func()->statusCode >= 100 && reply->d_func()->statusCode < 200)
- || reply->d_func()->statusCode == 204 || reply->d_func()->statusCode == 304)
- return false;
- if (reply->d_func()->request.operation() == QHttpNetworkRequest::Head)
- return !emitSignals(reply);
- if (reply->d_func()->contentLength() == 0)
- return false;
- return true;
-}
void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
QHttpNetworkReply *reply,
@@ -454,224 +226,13 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
int i = indexOf(socket);
// remove the corrupt data if any
- eraseData(channels[i].reply);
- closeChannel(i);
+ reply->d_func()->eraseData();
+ channels[i].close();
// send the next request
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
}
}
-#ifndef QT_NO_COMPRESS
-bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete)
-{
- Q_ASSERT(socket);
- Q_ASSERT(reply);
-
- qint64 total = bytesAvailable(*reply, true);
- if (total >= CHUNK || dataComplete) {
- int i = indexOf(socket);
- // uncompress the data
- QByteArray content, inflated;
- read(*reply, content, -1, true);
- int ret = Z_OK;
- if (content.size())
- ret = reply->d_func()->gunzipBodyPartially(content, inflated);
- int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK;
- if (ret >= retCheck) {
- if (inflated.size()) {
- reply->d_func()->totalProgress += inflated.size();
- appendData(*reply, inflated, false);
- if (emitSignals(reply)) {
- emit reply->readyRead();
- // make sure that the reply is valid
- if (channels[i].reply != reply)
- return true;
- emit reply->dataReadProgress(reply->d_func()->totalProgress, 0);
- // make sure that the reply is valid
- if (channels[i].reply != reply)
- return true;
-
- }
- }
- } else {
- emitReplyError(socket, reply, QNetworkReply::ProtocolFailure);
- return false;
- }
- }
- return true;
-}
-#endif
-
-void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply)
-{
- Q_ASSERT(socket);
-
- Q_Q(QHttpNetworkConnection);
- qint64 bytes = 0;
- QAbstractSocket::SocketState state = socket->state();
- int i = indexOf(socket);
-
- // connection might be closed to signal the end of data
- if (state == QAbstractSocket::UnconnectedState) {
- if (!socket->bytesAvailable()) {
- if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
- reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
- channels[i].state = IdleState;
- allDone(socket, reply);
- } else {
- // try to reconnect/resend before sending an error.
- if (channels[i].reconnectAttempts-- > 0) {
- resendCurrentRequest(socket);
- } else if (reply) {
- reply->d_func()->errorString = errorDetail(QNetworkReply::RemoteHostClosedError, socket);
- emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
- }
- }
- }
- }
-
- // read loop for the response
- while (socket->bytesAvailable()) {
- QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;
- switch (state) {
- case QHttpNetworkReplyPrivate::NothingDoneState:
- case QHttpNetworkReplyPrivate::ReadingStatusState: {
- qint64 statusBytes = reply->d_func()->readStatus(socket);
- if (statusBytes == -1) {
- // error reading the status, close the socket and emit error
- socket->close();
- reply->d_func()->errorString = errorDetail(QNetworkReply::ProtocolFailure, socket);
- emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString);
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
- break;
- }
- bytes += statusBytes;
- channels[i].lastStatus = reply->d_func()->statusCode;
- break;
- }
- case QHttpNetworkReplyPrivate::ReadingHeaderState:
- bytes += reply->d_func()->readHeader(socket);
- if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
- if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) {
- // remove the Content-Length from header
- reply->d_func()->removeAutoDecompressHeader();
- } else {
- reply->d_func()->autoDecompress = false;
- }
- if (reply && reply->d_func()->statusCode == 100) {
- reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
- break; // ignore
- }
- if (emitSignals(reply))
- emit reply->headerChanged();
- if (!expectContent(reply)) {
- reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
- channels[i].state = IdleState;
- allDone(socket, reply);
- return;
- }
- }
- break;
- case QHttpNetworkReplyPrivate::ReadingDataState: {
- QBuffer fragment;
- fragment.open(QIODevice::WriteOnly);
- bytes = reply->d_func()->readBody(socket, &fragment);
- if (bytes) {
- appendData(*reply, fragment.data(), reply->d_func()->autoDecompress);
- if (!reply->d_func()->autoDecompress) {
- reply->d_func()->totalProgress += fragment.size();
- if (emitSignals(reply)) {
- emit reply->readyRead();
- // make sure that the reply is valid
- if (channels[i].reply != reply)
- return;
- emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength);
- // make sure that the reply is valid
- if (channels[i].reply != reply)
- return;
- }
- }
-#ifndef QT_NO_COMPRESS
- else if (!expand(socket, reply, false)) { // expand a chunk if possible
- return; // ### expand failed
- }
-#endif
- }
- if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState)
- break;
- // everything done, fall through
- }
- case QHttpNetworkReplyPrivate::AllDoneState:
- channels[i].state = IdleState;
- allDone(socket, reply);
- break;
- default:
- break;
- }
- }
-}
-
-void QHttpNetworkConnectionPrivate::allDone(QAbstractSocket *socket, QHttpNetworkReply *reply)
-{
-#ifndef QT_NO_COMPRESS
- // expand the whole data.
- if (expectContent(reply) && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd)
- expand(socket, reply, true); // ### if expand returns false, its an error
-#endif
- // while handling 401 & 407, we might reset the status code, so save this.
- bool emitFinished = emitSignals(reply);
- handleStatus(socket, reply);
- // ### at this point there should be no more data on the socket
- // close if server requested
- int i = indexOf(socket);
- if (reply->d_func()->connectionCloseEnabled())
- closeChannel(i);
- // queue the finished signal, this is required since we might send new requests from
- // slot connected to it. The socket will not fire readyRead signal, if we are already
- // in the slot connected to readyRead
- if (emitFinished)
- QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection);
- // reset the reconnection attempts after we receive a complete reply.
- // in case of failures, each channel will attempt two reconnects before emitting error.
- channels[i].reconnectAttempts = 2;
-}
-
-void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply)
-{
- Q_ASSERT(socket);
- Q_ASSERT(reply);
-
- Q_Q(QHttpNetworkConnection);
-
- int statusCode = reply->statusCode();
- bool resend = false;
-
- switch (statusCode) {
- case 401:
- case 407:
- if (handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) {
- if (resend) {
- eraseData(reply);
- sendRequest(socket);
- }
- } else {
- int i = indexOf(socket);
- emit channels[i].reply->headerChanged();
- emit channels[i].reply->readyRead();
- QNetworkReply::NetworkError errorCode = (statusCode == 407)
- ? QNetworkReply::ProxyAuthenticationRequiredError
- : QNetworkReply::AuthenticationRequiredError;
- reply->d_func()->errorString = errorDetail(errorCode, socket);
- emit q->error(errorCode, reply->d_func()->errorString);
- emit channels[i].reply->finished();
- }
- break;
- default:
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
- }
-}
-
void QHttpNetworkConnectionPrivate::copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy)
{
Q_ASSERT(auth);
@@ -694,6 +255,7 @@ void QHttpNetworkConnectionPrivate::copyCredentials(int fromChannel, QAuthentica
}
+// handles the authentication for one channel and eventually re-starts the other channels
bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply,
bool isProxy, bool &resend)
{
@@ -733,14 +295,14 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
if (priv->phase == QAuthenticatorPrivate::Done) {
if ((isProxy && pendingProxyAuthSignal) ||(!isProxy && pendingAuthSignal)) {
// drop the request
- eraseData(channels[i].reply);
- closeChannel(i);
+ reply->d_func()->eraseData();
+ channels[i].close();
channels[i].lastStatus = 0;
- channels[i].state = Wait4AuthState;
+ channels[i].state = QHttpNetworkConnectionChannel::Wait4AuthState;
return false;
}
// cannot use this socket until the slot returns
- channels[i].state = WaitingState;
+ channels[i].state = QHttpNetworkConnectionChannel::WaitingState;
socket->blockSignals(true);
if (!isProxy) {
pendingAuthSignal = true;
@@ -755,11 +317,11 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
}
socket->blockSignals(false);
// socket free to use
- channels[i].state = IdleState;
+ channels[i].state = QHttpNetworkConnectionChannel::IdleState;
if (priv->phase != QAuthenticatorPrivate::Done) {
// send any pending requests
copyCredentials(i, auth, isProxy);
- QMetaObject::invokeMethod(q, "_q_restartPendingRequest", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(q, "_q_restartAuthPendingRequests", Qt::QueuedConnection);
}
}
// changing values in QAuthenticator will reset the 'phase'
@@ -778,8 +340,8 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
socket->close();
// remove pending request on the other channels
for (int j = 0; j < channelCount; ++j) {
- if (j != i && channels[j].state == Wait4AuthState)
- channels[j].state = IdleState;
+ if (j != i && channels[j].state == QHttpNetworkConnectionChannel::Wait4AuthState)
+ channels[j].state = QHttpNetworkConnectionChannel::IdleState;
}
return true;
}
@@ -839,62 +401,151 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
return reply;
}
-void QHttpNetworkConnectionPrivate::unqueueRequest(QAbstractSocket *socket)
+void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
+{
+ Q_Q(QHttpNetworkConnection);
+
+ QHttpNetworkRequest request = pair.first;
+ switch (request.priority()) {
+ case QHttpNetworkRequest::HighPriority:
+ highPriorityQueue.prepend(pair);
+ break;
+ case QHttpNetworkRequest::NormalPriority:
+ case QHttpNetworkRequest::LowPriority:
+ lowPriorityQueue.prepend(pair);
+ break;
+ }
+ QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
+}
+
+void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket)
{
Q_ASSERT(socket);
int i = indexOf(socket);
if (!highPriorityQueue.isEmpty()) {
- for (int j = highPriorityQueue.count() - 1; j >= 0; --j) {
- HttpMessagePair &messagePair = highPriorityQueue[j];
- if (!messagePair.second->d_func()->requestIsPrepared)
- prepareRequest(messagePair);
- if (!messagePair.second->d_func()->requestIsBuffering) {
- channels[i].request = messagePair.first;
- channels[i].reply = messagePair.second;
- sendRequest(socket);
- highPriorityQueue.removeAt(j);
- return;
- }
- }
+ // remove from queue before sendRequest! else we might pipeline the same request again
+ HttpMessagePair messagePair = highPriorityQueue.takeLast();
+ if (!messagePair.second->d_func()->requestIsPrepared)
+ prepareRequest(messagePair);
+ channels[i].request = messagePair.first;
+ channels[i].reply = messagePair.second;
+ channels[i].sendRequest();
+ return;
}
if (!lowPriorityQueue.isEmpty()) {
- for (int j = lowPriorityQueue.count() - 1; j >= 0; --j) {
- HttpMessagePair &messagePair = lowPriorityQueue[j];
- if (!messagePair.second->d_func()->requestIsPrepared)
- prepareRequest(messagePair);
- if (!messagePair.second->d_func()->requestIsBuffering) {
- channels[i].request = messagePair.first;
- channels[i].reply = messagePair.second;
- sendRequest(socket);
- lowPriorityQueue.removeAt(j);
- return;
- }
- }
+ // remove from queue before sendRequest! else we might pipeline the same request again
+ HttpMessagePair messagePair = lowPriorityQueue.takeLast();
+ if (!messagePair.second->d_func()->requestIsPrepared)
+ prepareRequest(messagePair);
+ channels[i].request = messagePair.first;
+ channels[i].reply = messagePair.second;
+ channels[i].sendRequest();
+ return;
}
}
-void QHttpNetworkConnectionPrivate::closeChannel(int channel)
+// this is called from _q_startNextRequest and when a request has been sent down a socket from the channel
+void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket)
{
- QAbstractSocket *socket = channels[channel].socket;
- socket->blockSignals(true);
- socket->close();
- socket->blockSignals(false);
- channels[channel].state = IdleState;
+ // return fast if there is nothing to pipeline
+ if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
+ return;
+
+ int i = indexOf(socket);
+
+ bool highPriorityQueueProcessingDone = false;
+ bool lowPriorityQueueProcessingDone = false;
+
+ while (!highPriorityQueueProcessingDone && !lowPriorityQueueProcessingDone) {
+ // this loop runs once per request we intend to pipeline in.
+
+ if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported)
+ return;
+
+ // the current request that is in must already support pipelining
+ if (!channels[i].request.isPipeliningAllowed())
+ return;
+
+ // the current request must be a idempotent (right now we only check GET)
+ if (channels[i].request.operation() != QHttpNetworkRequest::Get)
+ return;
+
+ // check if socket is connected
+ if (socket->state() != QAbstractSocket::ConnectedState)
+ return;
+
+ // check for resendCurrent
+ if (channels[i].resendCurrent)
+ return;
+
+ // we do not like authentication stuff
+ // ### make sure to be OK with this in later releases
+ if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty())
+ return;
+ if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty())
+ return;
+
+ // check for pipeline length
+ if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength)
+ return;
+
+ // must be in ReadingState or WaitingState
+ if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState
+ || channels[i].state == QHttpNetworkConnectionChannel::ReadingState))
+ return;
+
+ highPriorityQueueProcessingDone = fillPipeline(highPriorityQueue, channels[i]);
+ // not finished with highPriorityQueue? then loop again
+ if (!highPriorityQueueProcessingDone)
+ continue;
+ // highPriorityQueue was processed, now deal with the lowPriorityQueue
+ lowPriorityQueueProcessingDone = fillPipeline(lowPriorityQueue, channels[i]);
+ }
}
-void QHttpNetworkConnectionPrivate::resendCurrentRequest(QAbstractSocket *socket)
+// returns true when the processing of a queue has been done
+bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel)
{
- Q_Q(QHttpNetworkConnection);
- Q_ASSERT(socket);
- int i = indexOf(socket);
- closeChannel(i);
- channels[i].resendCurrent = true;
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
+ if (queue.isEmpty())
+ return true;
+
+ for (int i = queue.count() - 1; i >= 0; --i) {
+ HttpMessagePair messagePair = queue.at(i);
+ const QHttpNetworkRequest &request = messagePair.first;
+
+ // we currently do not support pipelining if HTTP authentication is used
+ if (!request.url().userInfo().isEmpty())
+ continue;
+
+ // take only GET requests
+ if (request.operation() != QHttpNetworkRequest::Get)
+ continue;
+
+ if (!request.isPipeliningAllowed())
+ continue;
+
+ // remove it from the queue
+ queue.takeAt(i);
+ // we modify the queue we iterate over here, but since we return from the function
+ // afterwards this is fine.
+
+ // actually send it
+ if (!messagePair.second->d_func()->requestIsPrepared)
+ prepareRequest(messagePair);
+ channel.pipelineInto(messagePair);
+
+ // return false because we processed something and need to process again
+ return false;
+ }
+
+ // return true, the queue has been processed and not changed
+ return true;
}
+
QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket)
{
Q_ASSERT(socket);
@@ -945,8 +596,8 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
for (int i = 0; i < channelCount; ++i) {
if (channels[i].reply == reply) {
channels[i].reply = 0;
- if (reply->d_func()->connectionCloseEnabled())
- closeChannel(i);
+ if (reply->d_func()->isConnectionCloseEnabled())
+ channels[i].close();
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
return;
}
@@ -976,263 +627,68 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
}
-//private slots
-void QHttpNetworkConnectionPrivate::_q_readyRead()
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return; // ### error
- if (isSocketWaiting(socket) || isSocketReading(socket)) {
- int i = indexOf(socket);
- channels[i].state = ReadingState;
- if (channels[i].reply)
- receiveReply(socket, channels[i].reply);
- }
- // ### error
-}
-
-void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes)
-{
- Q_UNUSED(bytes);
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return; // ### error
- if (isSocketWriting(socket))
- sendRequest(socket);
- // otherwise we do nothing
-}
-
-void QHttpNetworkConnectionPrivate::_q_disconnected()
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return; // ### error
- // read the available data before closing
- int i = indexOf(socket);
- if (isSocketWaiting(socket) || isSocketReading(socket)) {
- channels[i].state = ReadingState;
- if (channels[i].reply)
- receiveReply(socket, channels[i].reply);
- } else if (channels[i].state == IdleState && channels[i].resendCurrent) {
- // re-sending request because the socket was in ClosingState
- QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
- }
- channels[i].state = IdleState;
-}
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
{
- // send the current request again
- if (channels[0].resendCurrent || channels[1].resendCurrent) {
- int i = channels[0].resendCurrent ? 0:1;
- QAbstractSocket *socket = channels[i].socket;
- channels[i].resendCurrent = false;
- channels[i].state = IdleState;
- if (channels[i].reply)
- sendRequest(socket);
- return;
- }
- // send the request using the idle socket
- QAbstractSocket *socket = channels[0].socket;
- if (isSocketBusy(socket)) {
- socket = (isSocketBusy(channels[1].socket) ? 0 :channels[1].socket);
- }
-
- if (!socket) {
- return; // this will be called after finishing current request.
- }
- unqueueRequest(socket);
-}
-
-void QHttpNetworkConnectionPrivate::_q_restartPendingRequest()
-{
- // send the request using the idle socket
- for (int i = 0 ; i < channelCount; ++i) {
- QAbstractSocket *socket = channels[i].socket;
- if (channels[i].state == Wait4AuthState) {
- channels[i].state = IdleState;
+ //resend the necessary ones.
+ for (int i = 0; i < channelCount; ++i) {
+ if (channels[i].resendCurrent) {
+ channels[i].resendCurrent = false;
+ channels[i].state = QHttpNetworkConnectionChannel::IdleState;
if (channels[i].reply)
- sendRequest(socket);
+ channels[i].sendRequest();
}
}
-}
-
-void QHttpNetworkConnectionPrivate::_q_connected()
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return; // ### error
- int i = indexOf(socket);
- // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
- //channels[i].reconnectAttempts = 2;
- if (!channels[i].pendingEncrypt) {
- channels[i].state = IdleState;
- if (channels[i].reply)
- sendRequest(socket);
- else
- closeChannel(i);
+ QAbstractSocket *socket = 0;
+ for (int i = 0; i < channelCount; ++i) {
+ QAbstractSocket *chSocket = channels[i].socket;
+ // send the request using the idle socket
+ if (!channels[i].isSocketBusy()) {
+ socket = chSocket;
+ break;
+ }
}
-}
+ // this socket is free,
+ if (socket)
+ dequeueAndSendRequest(socket);
-void QHttpNetworkConnectionPrivate::_q_error(QAbstractSocket::SocketError socketError)
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
+ // try to push more into all sockets
+ // ### FIXME we should move this to the beginning of the function
+ // as soon as QtWebkit is properly using the pipelining
+ // (e.g. not for XMLHttpRequest or the first page load)
+ // ### FIXME we should also divide the requests more even
+ // on the connected sockets
+ //tryToFillPipeline(socket);
+ // return fast if there is nothing to pipeline
+ if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
return;
- bool send2Reply = false;
- int i = indexOf(socket);
- QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError;
-
- switch (socketError) {
- case QAbstractSocket::HostNotFoundError:
- errorCode = QNetworkReply::HostNotFoundError;
- break;
- case QAbstractSocket::ConnectionRefusedError:
- errorCode = QNetworkReply::ConnectionRefusedError;
- break;
- case QAbstractSocket::RemoteHostClosedError:
- // try to reconnect/resend before sending an error.
- // while "Reading" the _q_disconnected() will handle this.
- if (channels[i].state != IdleState && channels[i].state != ReadingState) {
- if (channels[i].reconnectAttempts-- > 0) {
- resendCurrentRequest(socket);
- return;
- } else {
- send2Reply = true;
- errorCode = QNetworkReply::RemoteHostClosedError;
- }
- } else {
- return;
- }
- break;
- case QAbstractSocket::SocketTimeoutError:
- // try to reconnect/resend before sending an error.
- if (channels[i].state == WritingState && (channels[i].reconnectAttempts-- > 0)) {
- resendCurrentRequest(socket);
- return;
- }
- send2Reply = true;
- errorCode = QNetworkReply::TimeoutError;
- break;
- case QAbstractSocket::ProxyAuthenticationRequiredError:
- errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
- break;
- case QAbstractSocket::SslHandshakeFailedError:
- errorCode = QNetworkReply::SslHandshakeFailedError;
- break;
- default:
- // all other errors are treated as NetworkError
- errorCode = QNetworkReply::UnknownNetworkError;
- break;
- }
- QPointer<QObject> that = q;
- QString errorString = errorDetail(errorCode, socket);
- if (send2Reply) {
- if (channels[i].reply) {
- channels[i].reply->d_func()->errorString = errorString;
- // this error matters only to this reply
- emit channels[i].reply->finishedWithError(errorCode, errorString);
- }
- // send the next request
- QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
- } else {
- // the failure affects all requests.
- emit q->error(errorCode, errorString);
- }
- if (that) //signals make enter the event loop
- closeChannel(i);
+ for (int j = 0; j < channelCount; j++)
+ fillPipeline(channels[j].socket);
}
-#ifndef QT_NO_NETWORKPROXY
-void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth)
+void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests()
{
- Q_Q(QHttpNetworkConnection);
- emit q->proxyAuthenticationRequired(proxy, auth, q);
-}
-#endif
-
-void QHttpNetworkConnectionPrivate::_q_dataReadyReadNoBuffer()
-{
- Q_Q(QHttpNetworkConnection);
- // data emitted either readyRead()
- // find out which channel it is for
- QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
-
- // won't match anything if the qobject_cast above failed
- for (int i = 0; i < channelCount; ++i) {
- if (sender == channels[i].request.data()) {
- sendRequest(channels[i].socket);
- break;
+ // send the request using the idle socket
+ for (int i = 0 ; i < channelCount; ++i) {
+ if (channels[i].state == QHttpNetworkConnectionChannel::Wait4AuthState) {
+ channels[i].state = QHttpNetworkConnectionChannel::IdleState;
+ if (channels[i].reply)
+ channels[i].sendRequest();
}
}
}
-void QHttpNetworkConnectionPrivate::_q_dataReadyReadBuffer()
-{
- Q_Q(QHttpNetworkConnection);
- QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
- HttpMessagePair *thePair = 0;
- for (int i = 0; !thePair && i < lowPriorityQueue.size(); ++i)
- if (lowPriorityQueue.at(i).first.data() == sender)
- thePair = &lowPriorityQueue[i];
-
- for (int i = 0; !thePair && i < highPriorityQueue.size(); ++i)
- if (highPriorityQueue.at(i).first.data() == sender)
- thePair = &highPriorityQueue[i];
-
- if (thePair) {
- bufferData(*thePair);
-
- // are we finished buffering?
- if (!thePair->second->d_func()->requestIsBuffering)
- _q_startNextRequest();
- }
-}
-void QHttpNetworkConnectionPrivate::bufferData(HttpMessagePair &messagePair)
+QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent)
+ : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent)
{
- Q_Q(QHttpNetworkConnection);
- QHttpNetworkRequest &request = messagePair.first;
- QHttpNetworkReply *reply = messagePair.second;
- Q_ASSERT(request.data());
- if (!reply->d_func()->requestIsBuffering) { // first time
- QObject::connect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
- QObject::connect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
- reply->d_func()->requestIsBuffering = true;
- reply->d_func()->requestDataBuffer.open(QIODevice::ReadWrite);
- }
-
- // always try to read at least one byte
- // ### FIXME! use a QRingBuffer
- qint64 bytesToRead = qMax<qint64>(1, request.data()->bytesAvailable());
- QByteArray newData;
- newData.resize(bytesToRead);
- qint64 bytesActuallyRead = request.data()->read(newData.data(), bytesToRead);
-
- if (bytesActuallyRead > 0) {
- // we read something
- newData.chop(bytesToRead - bytesActuallyRead);
- reply->d_func()->requestDataBuffer.write(newData);
- } else if (bytesActuallyRead == -1) { // last time
- QObject::disconnect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
- QObject::disconnect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
-
- request.setContentLength(reply->d_func()->requestDataBuffer.size());
- reply->d_func()->requestDataBuffer.seek(0);
- reply->d_func()->requestIsBuffering = false;
- }
+ Q_D(QHttpNetworkConnection);
+ d->init();
}
-// QHttpNetworkConnection
-
-QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent)
- : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent)
+QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent)
+ : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent)
{
Q_D(QHttpNetworkConnection);
d->init();
@@ -1324,29 +780,11 @@ QNetworkProxy QHttpNetworkConnection::transparentProxy() const
// SSL support below
#ifndef QT_NO_OPENSSL
-void QHttpNetworkConnectionPrivate::_q_encrypted()
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return; // ### error
- int i = indexOf(socket);
- channels[i].state = IdleState;
- sendRequest(socket);
-}
-
-void QHttpNetworkConnectionPrivate::_q_sslErrors(const QList<QSslError> &errors)
-{
- Q_Q(QHttpNetworkConnection);
- QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
- if (!socket)
- return;
- //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure;
- emit q->sslErrors(errors);
-}
-
QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNetworkReply &reply) const
{
+ if (!encrypt)
+ return QSslConfiguration();
+
for (int i = 0; i < channelCount; ++i)
if (channels[i].reply == &reply)
return static_cast<QSslSocket *>(channels[0].socket)->sslConfiguration();
@@ -1356,6 +794,9 @@ QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNet
void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config)
{
Q_D(QHttpNetworkConnection);
+ if (!d->encrypt)
+ return;
+
// set the config on all channels
for (int i = 0; i < d->channelCount; ++i)
static_cast<QSslSocket *>(d->channels[i].socket)->setSslConfiguration(config);
@@ -1364,21 +805,54 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config
void QHttpNetworkConnection::ignoreSslErrors(int channel)
{
Q_D(QHttpNetworkConnection);
+ if (!d->encrypt)
+ return;
+
if (channel == -1) { // ignore for all channels
for (int i = 0; i < d->channelCount; ++i) {
static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors();
- d->channels[i].ignoreSSLErrors = true;
+ d->channels[i].ignoreAllSslErrors = true;
}
} else {
static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors();
- d->channels[channel].ignoreSSLErrors = true;
+ d->channels[channel].ignoreAllSslErrors = true;
}
}
+void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int channel)
+{
+ Q_D(QHttpNetworkConnection);
+ if (!d->encrypt)
+ return;
+
+ if (channel == -1) { // ignore for all channels
+ for (int i = 0; i < d->channelCount; ++i) {
+ static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors);
+ d->channels[i].ignoreSslErrorsList = errors;
+ }
+
+ } else {
+ static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors);
+ d->channels[channel].ignoreSslErrorsList = errors;
+ }
+}
#endif //QT_NO_OPENSSL
+#ifndef QT_NO_NETWORKPROXY
+// only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not
+// from QHttpNetworkConnectionChannel::handleAuthenticationChallenge
+// e.g. it is for SOCKS proxies which require authentication.
+void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth)
+{
+ Q_Q(QHttpNetworkConnection);
+ emit q->proxyAuthenticationRequired(proxy, auth, q);
+ int i = indexOf(chan->socket);
+ copyCredentials(i, auth, true);
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index 7517bbb..36d0292 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -65,6 +65,7 @@
#include <private/qhttpnetworkrequest_p.h>
#include <private/qhttpnetworkreply_p.h>
+#include <private/qhttpnetworkconnectionchannel_p.h>
#ifndef QT_NO_HTTP
@@ -79,6 +80,7 @@ QT_BEGIN_NAMESPACE
class QHttpNetworkRequest;
class QHttpNetworkReply;
+class QByteArray;
class QHttpNetworkConnectionPrivate;
class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject
@@ -87,6 +89,7 @@ class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject
public:
QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0);
+ QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0);
~QHttpNetworkConnection();
//The hostname to which this is connected to.
@@ -116,6 +119,7 @@ public:
#ifndef QT_NO_OPENSSL
void setSslConfiguration(const QSslConfiguration &config);
void ignoreSslErrors(int channel = -1);
+ void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1);
Q_SIGNALS:
void sslErrors(const QList<QSslError> &errors);
@@ -135,29 +139,13 @@ private:
Q_DECLARE_PRIVATE(QHttpNetworkConnection)
Q_DISABLE_COPY(QHttpNetworkConnection)
friend class QHttpNetworkReply;
+ friend class QHttpNetworkConnectionChannel;
- Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64))
- Q_PRIVATE_SLOT(d_func(), void _q_readyRead())
- Q_PRIVATE_SLOT(d_func(), void _q_disconnected())
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
- Q_PRIVATE_SLOT(d_func(), void _q_restartPendingRequest())
- Q_PRIVATE_SLOT(d_func(), void _q_connected())
- Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError))
-#ifndef QT_NO_NETWORKPROXY
- Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))
-#endif
- Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadBuffer())
- Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadNoBuffer())
-
-#ifndef QT_NO_OPENSSL
- Q_PRIVATE_SLOT(d_func(), void _q_encrypted())
- Q_PRIVATE_SLOT(d_func(), void _q_sslErrors(const QList<QSslError>&))
-#endif
+ Q_PRIVATE_SLOT(d_func(), void _q_restartAuthPendingRequests())
};
-
-
// private classes
typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
@@ -166,129 +154,79 @@ class QHttpNetworkConnectionPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QHttpNetworkConnection)
public:
+ static const int defaultChannelCount;
+ static const int defaultPipelineLength;
+
QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
+ QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt);
~QHttpNetworkConnectionPrivate();
void init();
- void connectSignals(QAbstractSocket *socket);
-
- enum SocketState {
- IdleState = 0, // ready to send request
- ConnectingState = 1, // connecting to host
- WritingState = 2, // writing the data
- WaitingState = 4, // waiting for reply
- ReadingState = 8, // reading the reply
- Wait4AuthState = 0x10, // blocked for send till the current authentication slot is done
- BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState)
- };
enum { ChunkSize = 4096 };
int indexOf(QAbstractSocket *socket) const;
- bool isSocketBusy(QAbstractSocket *socket) const;
- bool isSocketWriting(QAbstractSocket *socket) const;
- bool isSocketWaiting(QAbstractSocket *socket) const;
- bool isSocketReading(QAbstractSocket *socket) const;
QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request);
- void unqueueRequest(QAbstractSocket *socket);
+ void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
+ void dequeueAndSendRequest(QAbstractSocket *socket);
void prepareRequest(HttpMessagePair &request);
- bool sendRequest(QAbstractSocket *socket);
- void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply);
- void resendCurrentRequest(QAbstractSocket *socket);
- void closeChannel(int channel);
+
+ void fillPipeline(QAbstractSocket *socket);
+ bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel);
+
void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy);
// private slots
- void _q_bytesWritten(qint64 bytes); // proceed sending
- void _q_readyRead(); // pending data to read
- void _q_disconnected(); // disconnected from host
void _q_startNextRequest(); // send the next request from the queue
- void _q_restartPendingRequest(); // send the currently blocked request
- void _q_connected(); // start sending request
- void _q_error(QAbstractSocket::SocketError); // error from socket
-#ifndef QT_NO_NETWORKPROXY
- void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy
-#endif
- void _q_dataReadyReadNoBuffer();
- void _q_dataReadyReadBuffer();
+ void _q_restartAuthPendingRequests(); // send the currently blocked request
void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
- bool ensureConnection(QAbstractSocket *socket);
+
QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket);
- void eraseData(QHttpNetworkReply *reply);
+
#ifndef QT_NO_COMPRESS
bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete);
#endif
- void bufferData(HttpMessagePair &request);
void removeReply(QHttpNetworkReply *reply);
QString hostName;
quint16 port;
bool encrypt;
- struct Channel {
- QAbstractSocket *socket;
- SocketState state;
- QHttpNetworkRequest request; // current request
- QHttpNetworkReply *reply; // current reply for this request
- qint64 written;
- qint64 bytesTotal;
- bool resendCurrent;
- int lastStatus; // last status received on this channel
- bool pendingEncrypt; // for https (send after encrypted)
- int reconnectAttempts; // maximum 2 reconnection attempts
- QAuthenticatorPrivate::Method authMehtod;
- QAuthenticatorPrivate::Method proxyAuthMehtod;
- QAuthenticator authenticator;
- QAuthenticator proxyAuthenticator;
-#ifndef QT_NO_OPENSSL
- bool ignoreSSLErrors;
-#endif
- Channel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false),
- lastStatus(0), pendingEncrypt(false), reconnectAttempts(2),
- authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None)
-#ifndef QT_NO_OPENSSL
- , ignoreSSLErrors(false)
-#endif
- {}
- };
- static const int channelCount;
- Channel channels[2]; // maximum of 2 socket connections to the server
+ const int channelCount;
+ QHttpNetworkConnectionChannel *channels; // parallel connections to the server
+
bool pendingAuthSignal; // there is an incomplete authentication signal
bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal
- void appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed);
- qint64 bytesAvailable(const QHttpNetworkReply &reply, bool compressed = false) const;
- qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed);
+ qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const;
+ qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const;
+
+
void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode);
bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
- void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply);
- void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply);
- inline bool emitSignals(QHttpNetworkReply *reply);
- inline bool expectContent(QHttpNetworkReply *reply);
+
#ifndef QT_NO_OPENSSL
- void _q_encrypted(); // start sending request (https)
- void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket
QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const;
#endif
#ifndef QT_NO_NETWORKPROXY
QNetworkProxy networkProxy;
+ void emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth);
#endif
//The request queues
QList<HttpMessagePair> highPriorityQueue;
QList<HttpMessagePair> lowPriorityQueue;
+
+ friend class QHttpNetworkConnectionChannel;
};
QT_END_NAMESPACE
-//Q_DECLARE_METATYPE(QHttpNetworkRequest)
-//Q_DECLARE_METATYPE(QHttpNetworkReply)
-
#endif // QT_NO_HTTP
#endif
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
new file mode 100644
index 0000000..aa6c64c
--- /dev/null
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -0,0 +1,884 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhttpnetworkconnection_p.h"
+#include "qhttpnetworkconnectionchannel_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
+
+#include <qpair.h>
+#include <qdebug.h>
+
+#ifndef QT_NO_HTTP
+
+#ifndef QT_NO_OPENSSL
+# include <QtNetwork/qsslkey.h>
+# include <QtNetwork/qsslcipher.h>
+# include <QtNetwork/qsslconfiguration.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp
+
+void QHttpNetworkConnectionChannel::init()
+{
+#ifndef QT_NO_OPENSSL
+ if (connection->d_func()->encrypt)
+ socket = new QSslSocket;
+ else
+ socket = new QTcpSocket;
+#else
+ socket = new QTcpSocket;
+#endif
+
+ QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(_q_bytesWritten(qint64)),
+ Qt::DirectConnection);
+ QObject::connect(socket, SIGNAL(connected()),
+ this, SLOT(_q_connected()),
+ Qt::DirectConnection);
+ QObject::connect(socket, SIGNAL(readyRead()),
+ this, SLOT(_q_readyRead()),
+ Qt::DirectConnection);
+ QObject::connect(socket, SIGNAL(disconnected()),
+ this, SLOT(_q_disconnected()),
+ Qt::DirectConnection);
+ QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(_q_error(QAbstractSocket::SocketError)),
+ Qt::DirectConnection);
+#ifndef QT_NO_NETWORKPROXY
+ QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
+ this, SLOT(_q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
+ Qt::DirectConnection);
+#endif
+
+#ifndef QT_NO_OPENSSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
+ if (sslSocket) {
+ // won't be a sslSocket if encrypt is false
+ QObject::connect(sslSocket, SIGNAL(encrypted()),
+ this, SLOT(_q_encrypted()),
+ Qt::DirectConnection);
+ QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError>&)),
+ this, SLOT(_q_sslErrors(const QList<QSslError>&)),
+ Qt::DirectConnection);
+ }
+#endif
+}
+
+
+void QHttpNetworkConnectionChannel::close()
+{
+ socket->blockSignals(true);
+ socket->close();
+ socket->blockSignals(false);
+ state = QHttpNetworkConnectionChannel::IdleState;
+}
+
+
+bool QHttpNetworkConnectionChannel::sendRequest()
+{
+ switch (state) {
+ case QHttpNetworkConnectionChannel::IdleState: { // write the header
+ if (!ensureConnection()) {
+ // wait for the connection (and encryption) to be done
+ // sendRequest will be called again from either
+ // _q_connected or _q_encrypted
+ return false;
+ }
+ written = 0; // excluding the header
+ bytesTotal = 0;
+ if (reply) {
+ reply->d_func()->clear();
+ reply->d_func()->connection = connection;
+ reply->d_func()->autoDecompress = request.d->autoDecompress;
+ reply->d_func()->pipeliningUsed = false;
+ }
+ state = QHttpNetworkConnectionChannel::WritingState;
+ pendingEncrypt = false;
+ // if the url contains authentication parameters, use the new ones
+ // both channels will use the new authentication parameters
+ if (!request.url().userInfo().isEmpty()) {
+ QUrl url = request.url();
+ QAuthenticator &auth = authenticator;
+ if (url.userName() != auth.user()
+ || (!url.password().isEmpty() && url.password() != auth.password())) {
+ auth.setUser(url.userName());
+ auth.setPassword(url.password());
+ connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
+ }
+ // clear the userinfo, since we use the same request for resending
+ // userinfo in url can conflict with the one in the authenticator
+ url.setUserInfo(QString());
+ request.setUrl(url);
+ }
+ connection->d_func()->createAuthorization(socket, request);
+#ifndef QT_NO_NETWORKPROXY
+ QByteArray header = QHttpNetworkRequestPrivate::header(request,
+ (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy));
+#else
+ QByteArray header = QHttpNetworkRequestPrivate::header(request, false);
+#endif
+ socket->write(header);
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (uploadByteDevice) {
+ // connect the signals so this function gets called again
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()),this, SLOT(_q_uploadDataReadyRead()));
+
+ bytesTotal = request.contentLength();
+ } else {
+ state = QHttpNetworkConnectionChannel::WaitingState;
+ sendRequest();
+ break;
+ }
+ // write the initial chunk together with the headers
+ // fall through
+ }
+ case QHttpNetworkConnectionChannel::WritingState:
+ {
+ // write the data
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (!uploadByteDevice || bytesTotal == written) {
+ if (uploadByteDevice)
+ emit reply->dataSendProgress(written, bytesTotal);
+ state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response
+ sendRequest();
+ break;
+ }
+
+ // only feed the QTcpSocket buffer when there is less than 32 kB in it
+ const qint64 socketBufferFill = 32*1024;
+ const qint64 socketWriteMaxSize = 16*1024;
+
+
+#ifndef QT_NO_OPENSSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
+ // if it is really an ssl socket, check more than just bytesToWrite()
+ while ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0))
+ <= socketBufferFill && bytesTotal != written)
+#else
+ while (socket->bytesToWrite() <= socketBufferFill
+ && bytesTotal != written)
+#endif
+ {
+ // get pointer to upload data
+ qint64 currentReadSize;
+ qint64 desiredReadSize = qMin(socketWriteMaxSize, bytesTotal - written);
+ const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize);
+
+ if (currentReadSize == -1) {
+ // premature eof happened
+ connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError);
+ return false;
+ break;
+ } else if (readPointer == 0 || currentReadSize == 0) {
+ // nothing to read currently, break the loop
+ break;
+ } else {
+ qint64 currentWriteSize = socket->write(readPointer, currentReadSize);
+ if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
+ // socket broke down
+ connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError);
+ return false;
+ } else {
+ written += currentWriteSize;
+ uploadByteDevice->advanceReadPointer(currentWriteSize);
+
+ emit reply->dataSendProgress(written, bytesTotal);
+
+ if (written == bytesTotal) {
+ // make sure this function is called once again
+ state = QHttpNetworkConnectionChannel::WaitingState;
+ sendRequest();
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case QHttpNetworkConnectionChannel::WaitingState:
+ {
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (uploadByteDevice) {
+ QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(_q_uploadDataReadyRead()));
+ }
+
+ // HTTP pipelining
+ connection->d_func()->fillPipeline(socket);
+ socket->flush();
+
+ // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called
+ // this is needed if the sends an reply before we have finished sending the request. In that
+ // case receiveReply had been called before but ignored the server reply
+ receiveReply();
+ break;
+ }
+ case QHttpNetworkConnectionChannel::ReadingState:
+ case QHttpNetworkConnectionChannel::Wait4AuthState:
+ // ignore _q_bytesWritten in these states
+ // fall through
+ default:
+ break;
+ }
+ return true;
+}
+
+
+void QHttpNetworkConnectionChannel::receiveReply()
+{
+ Q_ASSERT(socket);
+
+ qint64 bytes = 0;
+ QAbstractSocket::SocketState socketState = socket->state();
+
+ // connection might be closed to signal the end of data
+ if (socketState == QAbstractSocket::UnconnectedState) {
+ if (!socket->bytesAvailable()) {
+ if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
+ reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
+ this->state = QHttpNetworkConnectionChannel::IdleState;
+ allDone();
+ } else {
+ // try to reconnect/resend before sending an error.
+ if (reconnectAttempts-- > 0) {
+ closeAndResendCurrentRequest();
+ } else if (reply) {
+ reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket);
+ emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ }
+ }
+ }
+ }
+
+ // read loop for the response
+ while (socket->bytesAvailable()) {
+ QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;
+ switch (state) {
+ case QHttpNetworkReplyPrivate::NothingDoneState:
+ case QHttpNetworkReplyPrivate::ReadingStatusState: {
+ eatWhitespace();
+ qint64 statusBytes = reply->d_func()->readStatus(socket);
+ if (statusBytes == -1 && reconnectAttempts <= 0) {
+ // too many errors reading/receiving/parsing the status, close the socket and emit error
+ close();
+ reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::ProtocolFailure, socket);
+ emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString);
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ break;
+ } else if (statusBytes == -1) {
+ reconnectAttempts--;
+ reply->d_func()->clear();
+ closeAndResendCurrentRequest();
+ break;
+ }
+ bytes += statusBytes;
+ lastStatus = reply->d_func()->statusCode;
+ break;
+ }
+ case QHttpNetworkReplyPrivate::ReadingHeaderState:
+ bytes += reply->d_func()->readHeader(socket);
+ if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
+ if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) {
+ // remove the Content-Length from header
+ reply->d_func()->removeAutoDecompressHeader();
+ } else {
+ reply->d_func()->autoDecompress = false;
+ }
+ if (reply && reply->d_func()->statusCode == 100) {
+ reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
+ break; // ignore
+ }
+ if (reply->d_func()->shouldEmitSignals())
+ emit reply->headerChanged();
+ if (!reply->d_func()->expectContent()) {
+ reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
+ this->state = QHttpNetworkConnectionChannel::IdleState;
+ allDone();
+ return;
+ }
+ }
+ break;
+ case QHttpNetworkReplyPrivate::ReadingDataState: {
+ if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress
+ && reply->d_func()->bodyLength > 0) {
+ // bulk files like images should fulfill these properties and
+ // we can therefore save on memory copying
+ bytes = reply->d_func()->readBodyFast(socket, &reply->d_func()->responseData);
+ reply->d_func()->totalProgress += bytes;
+ if (reply->d_func()->shouldEmitSignals()) {
+ QPointer<QHttpNetworkReply> replyPointer = reply;
+ emit reply->readyRead();
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return;
+ emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength);
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return;
+ }
+ }
+ else
+ {
+ // use the traditional slower reading (for compressed encoding, chunked encoding,
+ // no content-length etc)
+ QByteDataBuffer byteDatas;
+ bytes = reply->d_func()->readBody(socket, &byteDatas);
+ if (bytes) {
+ if (reply->d_func()->autoDecompress)
+ reply->d_func()->appendCompressedReplyData(byteDatas);
+ else
+ reply->d_func()->appendUncompressedReplyData(byteDatas);
+
+ if (!reply->d_func()->autoDecompress) {
+ reply->d_func()->totalProgress += bytes;
+ if (reply->d_func()->shouldEmitSignals()) {
+ QPointer<QHttpNetworkReply> replyPointer = reply;
+ // important: At the point of this readyRead(), the byteDatas list must be empty,
+ // else implicit sharing will trigger memcpy when the user is reading data!
+ emit reply->readyRead();
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return;
+ emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength);
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return;
+ }
+ }
+#ifndef QT_NO_COMPRESS
+ else if (!expand(false)) { // expand a chunk if possible
+ return; // ### expand failed
+ }
+#endif
+ }
+ }
+ if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState)
+ break;
+ // everything done, fall through
+ }
+ case QHttpNetworkReplyPrivate::AllDoneState:
+ this->state = QHttpNetworkConnectionChannel::IdleState;
+ allDone();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+bool QHttpNetworkConnectionChannel::ensureConnection()
+{
+ // make sure that this socket is in a connected state, if not initiate
+ // connection to the host.
+ if (socket->state() != QAbstractSocket::ConnectedState) {
+ // connect to the host if not already connected.
+ // resend this request after we receive the disconnected signal
+ if (socket->state() == QAbstractSocket::ClosingState) {
+ resendCurrent = true;
+ return false;
+ }
+ state = QHttpNetworkConnectionChannel::ConnectingState;
+ pendingEncrypt = connection->d_func()->encrypt;
+
+ // reset state
+ pipeliningSupported = PipeliningSupportUnknown;
+
+ // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done"
+ // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the
+ // last header for Authorization is generated by the QAuthenticator. Basic & Digest logic does not
+ // check the "phase" for generating the Authorization header. NTLM authentication is a two stage
+ // process & needs the "phase". To make sure the QAuthenticator uses the current username/password
+ // the phase is reset to Start.
+ QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(authenticator);
+ if (priv && priv->phase == QAuthenticatorPrivate::Done)
+ priv->phase = QAuthenticatorPrivate::Start;
+ priv = QAuthenticatorPrivate::getPrivate(proxyAuthenticator);
+ if (priv && priv->phase == QAuthenticatorPrivate::Done)
+ priv->phase = QAuthenticatorPrivate::Start;
+
+ QString connectHost = connection->d_func()->hostName;
+ qint16 connectPort = connection->d_func()->port;
+
+#ifndef QT_NO_NETWORKPROXY
+ // HTTPS always use transparent proxy.
+ if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !connection->d_func()->encrypt) {
+ connectHost = connection->d_func()->networkProxy.hostName();
+ connectPort = connection->d_func()->networkProxy.port();
+ }
+#endif
+ if (connection->d_func()->encrypt) {
+#ifndef QT_NO_OPENSSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
+ sslSocket->connectToHostEncrypted(connectHost, connectPort);
+ if (ignoreAllSslErrors)
+ sslSocket->ignoreSslErrors();
+ sslSocket->ignoreSslErrors(ignoreSslErrorsList);
+#else
+ connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError);
+#endif
+ } else {
+ socket->connectToHost(connectHost, connectPort);
+ }
+ return false;
+ }
+ return true;
+}
+
+
+#ifndef QT_NO_COMPRESS
+bool QHttpNetworkConnectionChannel::expand(bool dataComplete)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(reply);
+
+ qint64 total = reply->d_func()->compressedData.size();
+ if (total >= CHUNK || dataComplete) {
+ // uncompress the data
+ QByteArray content, inflated;
+ content = reply->d_func()->compressedData;
+ reply->d_func()->compressedData.clear();
+
+ int ret = Z_OK;
+ if (content.size())
+ ret = reply->d_func()->gunzipBodyPartially(content, inflated);
+ int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK;
+ if (ret >= retCheck) {
+ if (inflated.size()) {
+ reply->d_func()->totalProgress += inflated.size();
+ reply->d_func()->appendUncompressedReplyData(inflated);
+ if (reply->d_func()->shouldEmitSignals()) {
+ QPointer<QHttpNetworkReply> replyPointer = reply;
+ // important: At the point of this readyRead(), inflated must be cleared,
+ // else implicit sharing will trigger memcpy when the user is reading data!
+ emit reply->readyRead();
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return true;
+ emit reply->dataReadProgress(reply->d_func()->totalProgress, 0);
+ // make sure that the reply is valid
+ if (replyPointer.isNull())
+ return true;
+
+ }
+ }
+ } else {
+ connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolFailure);
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
+
+void QHttpNetworkConnectionChannel::allDone()
+{
+#ifndef QT_NO_COMPRESS
+ // expand the whole data.
+ if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd)
+ expand(true); // ### if expand returns false, its an error
+#endif
+ // while handling 401 & 407, we might reset the status code, so save this.
+ bool emitFinished = reply->d_func()->shouldEmitSignals();
+ handleStatus();
+ // ### at this point there should be no more data on the socket
+ // close if server requested
+ if (reply->d_func()->isConnectionCloseEnabled())
+ close();
+ // queue the finished signal, this is required since we might send new requests from
+ // slot connected to it. The socket will not fire readyRead signal, if we are already
+ // in the slot connected to readyRead
+ if (emitFinished)
+ QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection);
+ // reset the reconnection attempts after we receive a complete reply.
+ // in case of failures, each channel will attempt two reconnects before emitting error.
+ reconnectAttempts = 2;
+
+ detectPipeliningSupport();
+
+ // move next from pipeline to current request
+ if (!alreadyPipelinedRequests.isEmpty()) {
+ if (resendCurrent || reply->d_func()->isConnectionCloseEnabled() || socket->state() != QAbstractSocket::ConnectedState) {
+ // move the pipelined ones back to the main queue
+ requeueCurrentlyPipelinedRequests();
+ } else {
+ // there were requests pipelined in and we can continue
+ HttpMessagePair messagePair = alreadyPipelinedRequests.takeFirst();
+
+ request = messagePair.first;
+ reply = messagePair.second;
+ state = QHttpNetworkConnectionChannel::ReadingState;
+ resendCurrent = false;
+
+ written = 0; // message body, excluding the header, irrelevant here
+ bytesTotal = 0; // message body total, excluding the header, irrelevant here
+
+ // pipeline even more
+ connection->d_func()->fillPipeline(socket);
+
+ // continue reading
+ receiveReply();
+ }
+ } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) {
+ eatWhitespace();
+ // this is weird. we had nothing pipelined but still bytes available. better close it.
+ if (socket->bytesAvailable() > 0)
+ close();
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ } else if (alreadyPipelinedRequests.isEmpty()) {
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ }
+}
+
+void QHttpNetworkConnectionChannel::detectPipeliningSupport()
+{
+ // detect HTTP Pipelining support
+ QByteArray serverHeaderField = reply->headerField("Server");
+ if (
+ // check for broken servers in server reply header
+ // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
+ (!serverHeaderField.contains("Microsoft-IIS/4."))
+ && (!serverHeaderField.contains("Microsoft-IIS/5."))
+ && (!serverHeaderField.contains("Netscape-Enterprise/3."))
+ // check for HTTP/1.1
+ && (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)
+ // check for not having connection close
+ && (!reply->d_func()->isConnectionCloseEnabled())
+ // check if it is still connected
+ && (socket->state() == QAbstractSocket::ConnectedState)
+ ) {
+ pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported;
+ } else {
+ pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown;
+ }
+}
+
+// called when the connection broke and we need to queue some pipelined requests again
+void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests()
+{
+ for (int i = 0; i < alreadyPipelinedRequests.length(); i++)
+ connection->d_func()->requeueRequest(alreadyPipelinedRequests.at(i));
+ alreadyPipelinedRequests.clear();
+
+ close();
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+}
+
+void QHttpNetworkConnectionChannel::eatWhitespace()
+{
+ char c;
+ while (socket->bytesAvailable()) {
+ if (socket->peek(&c, 1) != 1)
+ return;
+
+ // read all whitespace and line endings
+ if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) {
+ socket->read(&c, 1);
+ continue;
+ } else {
+ break;
+ }
+ }
+}
+
+void QHttpNetworkConnectionChannel::handleStatus()
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(reply);
+
+ int statusCode = reply->statusCode();
+ bool resend = false;
+
+ switch (statusCode) {
+ case 401: // auth required
+ case 407: // proxy auth required
+ if (connection->d_func()->handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) {
+ if (resend) {
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (uploadByteDevice) {
+ if (uploadByteDevice->reset()) {
+ written = 0;
+ } else {
+ connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError);
+ break;
+ }
+ }
+
+ reply->d_func()->eraseData();
+
+ if (alreadyPipelinedRequests.isEmpty()) {
+ // this does a re-send without closing the connection
+ resendCurrent = true;
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ } else {
+ // we had requests pipelined.. better close the connection in closeAndResendCurrentRequest
+ closeAndResendCurrentRequest();
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ }
+ }
+ } else {
+ emit reply->headerChanged();
+ emit reply->readyRead();
+ QNetworkReply::NetworkError errorCode = (statusCode == 407)
+ ? QNetworkReply::ProxyAuthenticationRequiredError
+ : QNetworkReply::AuthenticationRequiredError;
+ reply->d_func()->errorString = connection->d_func()->errorDetail(errorCode, socket);
+ emit connection->error(errorCode, reply->d_func()->errorString);
+ emit reply->finished();
+ }
+ break;
+ default:
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ }
+}
+
+void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair)
+{
+ // this is only called for simple GET
+
+ QHttpNetworkRequest &request = pair.first;
+ QHttpNetworkReply *reply = pair.second;
+ if (reply) {
+ reply->d_func()->clear();
+ reply->d_func()->connection = connection;
+ reply->d_func()->autoDecompress = request.d->autoDecompress;
+ reply->d_func()->pipeliningUsed = true;
+ }
+
+#ifndef QT_NO_NETWORKPROXY
+ QByteArray header = QHttpNetworkRequestPrivate::header(request,
+ (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy));
+#else
+ QByteArray header = QHttpNetworkRequestPrivate::header(request, false);
+#endif
+ socket->write(header);
+
+ alreadyPipelinedRequests.append(pair);
+}
+
+void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest()
+{
+ requeueCurrentlyPipelinedRequests();
+ close();
+ resendCurrent = true;
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+}
+
+bool QHttpNetworkConnectionChannel::isSocketBusy() const
+{
+ return (state & QHttpNetworkConnectionChannel::BusyState);
+}
+
+bool QHttpNetworkConnectionChannel::isSocketWriting() const
+{
+ return (state & QHttpNetworkConnectionChannel::WritingState);
+}
+
+bool QHttpNetworkConnectionChannel::isSocketWaiting() const
+{
+ return (state & QHttpNetworkConnectionChannel::WaitingState);
+}
+
+bool QHttpNetworkConnectionChannel::isSocketReading() const
+{
+ return (state & QHttpNetworkConnectionChannel::ReadingState);
+}
+
+//private slots
+void QHttpNetworkConnectionChannel::_q_readyRead()
+{
+ if (isSocketWaiting() || isSocketReading()) {
+ state = QHttpNetworkConnectionChannel::ReadingState;
+ if (reply)
+ receiveReply();
+ }
+}
+
+void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes)
+{
+ Q_UNUSED(bytes);
+ // bytes have been written to the socket. write even more of them :)
+ if (isSocketWriting())
+ sendRequest();
+ // otherwise we do nothing
+}
+
+void QHttpNetworkConnectionChannel::_q_disconnected()
+{
+ // read the available data before closing
+ if (isSocketWaiting() || isSocketReading()) {
+ state = QHttpNetworkConnectionChannel::ReadingState;
+ if (reply)
+ receiveReply();
+ } else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) {
+ // re-sending request because the socket was in ClosingState
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ }
+ state = QHttpNetworkConnectionChannel::IdleState;
+
+ requeueCurrentlyPipelinedRequests();
+}
+
+
+void QHttpNetworkConnectionChannel::_q_connected()
+{
+ // improve performance since we get the request sent by the kernel ASAP
+ socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
+
+ pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown;
+
+ // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again!
+ //channels[i].reconnectAttempts = 2;
+ if (!pendingEncrypt) {
+ state = QHttpNetworkConnectionChannel::IdleState;
+ if (reply)
+ sendRequest();
+ else
+ close();
+ }
+}
+
+
+void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socketError)
+{
+ if (!socket)
+ return;
+ bool send2Reply = false;
+ QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError;
+
+ switch (socketError) {
+ case QAbstractSocket::HostNotFoundError:
+ errorCode = QNetworkReply::HostNotFoundError;
+ break;
+ case QAbstractSocket::ConnectionRefusedError:
+ errorCode = QNetworkReply::ConnectionRefusedError;
+ break;
+ case QAbstractSocket::RemoteHostClosedError:
+ // try to reconnect/resend before sending an error.
+ // while "Reading" the _q_disconnected() will handle this.
+ if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
+ if (reconnectAttempts-- > 0) {
+ closeAndResendCurrentRequest();
+ return;
+ } else {
+ send2Reply = true;
+ errorCode = QNetworkReply::RemoteHostClosedError;
+ }
+ } else {
+ return;
+ }
+ break;
+ case QAbstractSocket::SocketTimeoutError:
+ // try to reconnect/resend before sending an error.
+ if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) {
+ closeAndResendCurrentRequest();
+ return;
+ }
+ send2Reply = true;
+ errorCode = QNetworkReply::TimeoutError;
+ break;
+ case QAbstractSocket::ProxyAuthenticationRequiredError:
+ errorCode = QNetworkReply::ProxyAuthenticationRequiredError;
+ break;
+ case QAbstractSocket::SslHandshakeFailedError:
+ errorCode = QNetworkReply::SslHandshakeFailedError;
+ break;
+ default:
+ // all other errors are treated as NetworkError
+ errorCode = QNetworkReply::UnknownNetworkError;
+ break;
+ }
+ QPointer<QObject> that = connection;
+ QString errorString = connection->d_func()->errorDetail(errorCode, socket);
+ if (send2Reply) {
+ if (reply) {
+ reply->d_func()->errorString = errorString;
+ // this error matters only to this reply
+ emit reply->finishedWithError(errorCode, errorString);
+ }
+ // send the next request
+ QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
+ } else {
+ // the failure affects all requests.
+ emit connection->error(errorCode, errorString);
+ }
+ if (that) //signal emission triggered event loop
+ close();
+}
+
+#ifndef QT_NO_NETWORKPROXY
+void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth)
+{
+ connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth);
+}
+#endif
+
+void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead()
+{
+ sendRequest();
+}
+
+#ifndef QT_NO_OPENSSL
+void QHttpNetworkConnectionChannel::_q_encrypted()
+{
+ if (!socket)
+ return; // ### error
+ state = QHttpNetworkConnectionChannel::IdleState;
+ sendRequest();
+}
+
+void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
+{
+ if (!socket)
+ return;
+ //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure;
+ emit connection->sslErrors(errors);
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "moc_qhttpnetworkconnectionchannel_p.cpp"
+
+#endif // QT_NO_HTTP
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
new file mode 100644
index 0000000..9aa7597
--- /dev/null
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHTTPNETWORKCONNECTIONCHANNEL_H
+#define QHTTPNETWORKCONNECTIONCHANNEL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Network Access API. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+#include <QtNetwork/qnetworkrequest.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qabstractsocket.h>
+
+#include <private/qobject_p.h>
+#include <qauthenticator.h>
+#include <qnetworkproxy.h>
+#include <qbuffer.h>
+
+#include <private/qhttpnetworkheader_p.h>
+#include <private/qhttpnetworkrequest_p.h>
+#include <private/qhttpnetworkreply_p.h>
+
+
+#ifndef QT_NO_HTTP
+
+#ifndef QT_NO_OPENSSL
+# include <QtNetwork/qsslsocket.h>
+# include <QtNetwork/qsslerror.h>
+#else
+# include <QtNetwork/qtcpsocket.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QHttpNetworkRequest;
+class QHttpNetworkReply;
+class QByteArray;
+class QHttpNetworkConnection;
+
+#ifndef HttpMessagePair
+typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
+#endif
+
+class QHttpNetworkConnectionChannel : public QObject {
+ Q_OBJECT
+public:
+ enum ChannelState {
+ IdleState = 0, // ready to send request
+ ConnectingState = 1, // connecting to host
+ WritingState = 2, // writing the data
+ WaitingState = 4, // waiting for reply
+ ReadingState = 8, // reading the reply
+ Wait4AuthState = 0x10, // blocked for send till the current authentication slot is done
+ BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState)
+ };
+ QAbstractSocket *socket;
+ ChannelState state;
+ QHttpNetworkRequest request; // current request
+ QHttpNetworkReply *reply; // current reply for this request
+ qint64 written;
+ qint64 bytesTotal;
+ bool resendCurrent;
+ int lastStatus; // last status received on this channel
+ bool pendingEncrypt; // for https (send after encrypted)
+ int reconnectAttempts; // maximum 2 reconnection attempts
+ QAuthenticatorPrivate::Method authMehtod;
+ QAuthenticatorPrivate::Method proxyAuthMehtod;
+ QAuthenticator authenticator;
+ QAuthenticator proxyAuthenticator;
+#ifndef QT_NO_OPENSSL
+ bool ignoreAllSslErrors;
+ QList<QSslError> ignoreSslErrorsList;
+#endif
+
+ // HTTP pipelining -> http://en.wikipedia.org/wiki/Http_pipelining
+ enum PipeliningSupport {
+ PipeliningSupportUnknown, // default for a new connection
+ PipeliningProbablySupported, // after having received a server response that indicates support
+ PipeliningNotSupported // currently not used
+ };
+ PipeliningSupport pipeliningSupported;
+ QList<HttpMessagePair> alreadyPipelinedRequests;
+
+
+ QHttpNetworkConnectionChannel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false),
+ lastStatus(0), pendingEncrypt(false), reconnectAttempts(2),
+ authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None)
+#ifndef QT_NO_OPENSSL
+ , ignoreAllSslErrors(false)
+#endif
+ , pipeliningSupported(PipeliningSupportUnknown)
+ , connection(0)
+ {}
+
+ void setConnection(QHttpNetworkConnection *c) {connection = c;}
+ QHttpNetworkConnection *connection;
+
+ void init();
+ void close();
+
+ bool sendRequest();
+ void receiveReply();
+
+ bool ensureConnection();
+
+ bool expand(bool dataComplete);
+ void allDone(); // reply header + body have been read
+ void handleStatus(); // called from allDone()
+
+ void pipelineInto(HttpMessagePair &pair);
+ void requeueCurrentlyPipelinedRequests();
+ void detectPipeliningSupport();
+
+ void closeAndResendCurrentRequest();
+
+ void eatWhitespace();
+
+ bool isSocketBusy() const;
+ bool isSocketWriting() const;
+ bool isSocketWaiting() const;
+ bool isSocketReading() const;
+
+ protected slots:
+ void _q_bytesWritten(qint64 bytes); // proceed sending
+ void _q_readyRead(); // pending data to read
+ void _q_disconnected(); // disconnected from host
+ void _q_connected(); // start sending request
+ void _q_error(QAbstractSocket::SocketError); // error from socket
+#ifndef QT_NO_NETWORKPROXY
+ void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy
+#endif
+
+ void _q_uploadDataReadyRead();
+
+#ifndef QT_NO_OPENSSL
+ void _q_encrypted(); // start sending request (https)
+ void _q_sslErrors(const QList<QSslError> &errors); // ssl errors from the socket
+#endif
+};
+
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_HTTP
+
+#endif
diff --git a/src/network/access/qhttpnetworkheader.cpp b/src/network/access/qhttpnetworkheader.cpp
index 68ed3e5..cfe67f2 100644
--- a/src/network/access/qhttpnetworkheader.cpp
+++ b/src/network/access/qhttpnetworkheader.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qhttpnetworkheader_p.h b/src/network/access/qhttpnetworkheader_p.h
index 9dae42e..870e153 100644
--- a/src/network/access/qhttpnetworkheader_p.h
+++ b/src/network/access/qhttpnetworkheader_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index fe51cb7..539c7e2 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -162,18 +162,24 @@ qint64 QHttpNetworkReply::bytesAvailable() const
{
Q_D(const QHttpNetworkReply);
if (d->connection)
- return d->connection->d_func()->bytesAvailable(*this);
+ return d->connection->d_func()->uncompressedBytesAvailable(*this);
else
return -1;
}
-QByteArray QHttpNetworkReply::read(qint64 maxSize)
+qint64 QHttpNetworkReply::bytesAvailableNextBlock() const
{
- Q_D(QHttpNetworkReply);
- QByteArray data;
+ Q_D(const QHttpNetworkReply);
if (d->connection)
- d->connection->d_func()->read(*this, data, maxSize, false);
- return data;
+ return d->connection->d_func()->uncompressedBytesAvailableNextBlock(*this);
+ else
+ return -1;
+}
+
+QByteArray QHttpNetworkReply::readAny()
+{
+ Q_D(QHttpNetworkReply);
+ return d->responseData.read();
}
bool QHttpNetworkReply::isFinished() const
@@ -181,13 +187,20 @@ bool QHttpNetworkReply::isFinished() const
return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState;
}
+bool QHttpNetworkReply::isPipeliningUsed() const
+{
+ return d_func()->pipeliningUsed;
+}
QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
: QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100),
majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0),
+ chunkedTransferEncoding(false),
+ connectionCloseEnabled(true),
currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false),
- autoDecompress(false), requestIsBuffering(false), requestIsPrepared(false)
+ autoDecompress(false), responseData(), requestIsPrepared(false)
+ ,pipeliningUsed(false)
{
}
@@ -204,6 +217,7 @@ void QHttpNetworkReplyPrivate::clear()
totalProgress = 0;
currentChunkSize = 0;
currentChunkRead = 0;
+ connectionCloseEnabled = true;
connection = 0;
#ifndef QT_NO_COMPRESS
if (initInflate)
@@ -411,20 +425,26 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
}
bool ok = parseStatus(fragment);
state = ReadingHeaderState;
- fragment.clear(); // next fragment
-
- if (!ok)
+ fragment.clear();
+ if (!ok) {
return -1;
+ }
break;
} else {
c = 0;
- bytes += socket->read(&c, 1);
+ int haveRead = socket->read(&c, 1);
+ if (haveRead == -1)
+ return -1;
+ bytes += haveRead;
fragment.append(c);
}
// is this a valid reply?
if (fragment.length() >= 5 && !fragment.startsWith("HTTP/"))
+ {
+ fragment.clear();
return -1;
+ }
}
@@ -470,8 +490,6 @@ bool QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status)
qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
{
qint64 bytes = 0;
- char crlfcrlf[5];
- crlfcrlf[4] = '\0';
char c = 0;
bool allHeaders = false;
while (!allHeaders && socket->bytesAvailable()) {
@@ -491,6 +509,16 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
state = ReadingDataState;
fragment.clear(); // next fragment
bodyLength = contentLength(); // cache the length
+
+ // cache isChunked() since it is called often
+ chunkedTransferEncoding = headerField("transfer-encoding").toLower().contains("chunked");
+
+ // cache isConnectionCloseEnabled since it is called often
+ QByteArray connectionHeaderField = headerField("connection");
+ // check for explicit indication of close or the implicit connection close of HTTP/1.0
+ connectionCloseEnabled = (connectionHeaderField.toLower().contains("close") ||
+ headerField("proxy-connection").toLower().contains("close")) ||
+ (majorVersion == 1 && minorVersion == 0 && connectionHeaderField.isEmpty());
}
return bytes;
}
@@ -531,60 +559,84 @@ void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header)
bool QHttpNetworkReplyPrivate::isChunked()
{
- return headerField("transfer-encoding").toLower().contains("chunked");
+ return chunkedTransferEncoding;
+}
+
+bool QHttpNetworkReplyPrivate::isConnectionCloseEnabled()
+{
+ return connectionCloseEnabled;
}
-bool QHttpNetworkReplyPrivate::connectionCloseEnabled()
+// note this function can only be used for non-chunked, non-compressed with
+// known content length
+qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb)
{
- return (headerField("connection").toLower().contains("close") ||
- headerField("proxy-connection").toLower().contains("close"));
+ qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead);
+ QByteArray bd;
+ bd.resize(toBeRead);
+ qint64 haveRead = socket->read(bd.data(), bd.size());
+ if (haveRead == -1) {
+ bd.clear();
+ return 0; // ### error checking here;
+ }
+ bd.resize(haveRead);
+
+ rb->append(bd);
+
+ if (contentRead + haveRead == bodyLength) {
+ state = AllDoneState;
+ }
+
+ contentRead += haveRead;
+ return haveRead;
}
-qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out)
+
+qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuffer *out)
{
qint64 bytes = 0;
if (isChunked()) {
- bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6)
+ bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6)
} else if (bodyLength > 0) { // we have a Content-Length
- bytes += transferRaw(socket, out, bodyLength - contentRead);
+ bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead);
if (contentRead + bytes == bodyLength)
state = AllDoneState;
} else {
- bytes += transferRaw(socket, out, socket->bytesAvailable());
+ bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
}
- if (state == AllDoneState)
- socket->readAll(); // Read the rest to clean (CRLF)
contentRead += bytes;
return bytes;
}
-qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size)
+qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size)
{
qint64 bytes = 0;
Q_ASSERT(in);
Q_ASSERT(out);
int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable()));
- QByteArray raw(toBeRead, 0);
- while (size > 0) {
- qint64 read = in->read(raw.data(), raw.size());
- if (read == 0)
- return bytes;
- // ### error checking here
- qint64 written = out->write(raw.data(), read);
- if (written == 0)
+ while (toBeRead > 0) {
+ QByteArray byteData;
+ byteData.resize(toBeRead);
+ qint64 haveRead = in->read(byteData.data(), byteData.size());
+ if (haveRead <= 0) {
+ // ### error checking here
+ byteData.clear();
return bytes;
- if (read != written)
- qDebug() << "### read" << read << "written" << written;
- bytes += read;
- size -= read;
- out->waitForBytesWritten(-1); // throttle
+ }
+
+ byteData.resize(haveRead);
+ out->append(byteData);
+ bytes += haveRead;
+ size -= haveRead;
+
+ toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable()));
}
return bytes;
}
-qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out)
+qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out)
{
qint64 bytes = 0;
while (in->bytesAvailable()) { // while we can read from input
@@ -605,17 +657,14 @@ qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out)
state = AllDoneState;
break;
}
- // otherwise, read data
- qint64 readSize = qMin(in->bytesAvailable(), currentChunkSize - currentChunkRead);
- QByteArray buffer(readSize, 0);
- qint64 read = in->read(buffer.data(), readSize);
- bytes += read;
- currentChunkRead += read;
- qint64 written = out->write(buffer);
- Q_UNUSED(written); // Avoid compile warning when building release
- Q_ASSERT(read == written);
+
+ // otherwise, try to read what is missing for this chunk
+ qint64 haveRead = readReplyBodyRaw (in, out, currentChunkSize - currentChunkRead);
+ currentChunkRead += haveRead;
+ bytes += haveRead;
+
// ### error checking here
- out->waitForBytesWritten(-1);
+
}
return bytes;
}
@@ -652,6 +701,63 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize)
return bytes;
}
+void QHttpNetworkReplyPrivate::appendUncompressedReplyData(QByteArray &qba)
+{
+ responseData.append(qba);
+
+ // clear the original! helps with implicit sharing and
+ // avoiding memcpy when the user is reading the data
+ qba.clear();
+}
+
+void QHttpNetworkReplyPrivate::appendUncompressedReplyData(QByteDataBuffer &data)
+{
+ responseData.append(data);
+
+ // clear the original! helps with implicit sharing and
+ // avoiding memcpy when the user is reading the data
+ data.clear();
+}
+
+void QHttpNetworkReplyPrivate::appendCompressedReplyData(QByteDataBuffer &data)
+{
+ // Work in progress: Later we will directly use a list of QByteArray or a QRingBuffer
+ // instead of one QByteArray.
+ for(int i = 0; i < data.bufferCount(); i++) {
+ QByteArray &byteData = data[i];
+ compressedData.append(byteData.constData(), byteData.size());
+ }
+ data.clear();
+}
+
+
+bool QHttpNetworkReplyPrivate::shouldEmitSignals()
+{
+ // for 401 & 407 don't emit the data signals. Content along with these
+ // responses are send only if the authentication fails.
+ return (statusCode != 401 && statusCode != 407);
+}
+
+bool QHttpNetworkReplyPrivate::expectContent()
+{
+ // check whether we can expect content after the headers (rfc 2616, sec4.4)
+ if ((statusCode >= 100 && statusCode < 200)
+ || statusCode == 204 || statusCode == 304)
+ return false;
+ if (request.operation() == QHttpNetworkRequest::Head)
+ return !shouldEmitSignals();
+ if (contentLength() == 0)
+ return false;
+ return true;
+}
+
+void QHttpNetworkReplyPrivate::eraseData()
+{
+ compressedData.clear();
+ responseData.clear();
+}
+
+
// SSL support below
#ifndef QT_NO_OPENSSL
@@ -677,6 +783,13 @@ void QHttpNetworkReply::ignoreSslErrors()
d->connection->ignoreSslErrors();
}
+void QHttpNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ Q_D(QHttpNetworkReply);
+ if (d->connection)
+ d->connection->ignoreSslErrors(errors);
+}
+
#endif //QT_NO_OPENSSL
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 8f120a8..702e746 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -80,6 +80,8 @@ static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header
#include <private/qhttpnetworkheader_p.h>
#include <private/qhttpnetworkrequest_p.h>
#include <private/qauthenticator_p.h>
+#include <private/qringbuffer_p.h>
+#include <private/qbytedata_p.h>
QT_BEGIN_NAMESPACE
@@ -121,14 +123,18 @@ public:
QString reasonPhrase() const;
qint64 bytesAvailable() const;
- QByteArray read(qint64 maxSize = -1);
+ qint64 bytesAvailableNextBlock() const;
+ QByteArray readAny();
bool isFinished() const;
+ bool isPipeliningUsed() const;
+
#ifndef QT_NO_OPENSSL
QSslConfiguration sslConfiguration() const;
void setSslConfiguration(const QSslConfiguration &config);
void ignoreSslErrors();
+ void ignoreSslErrors(const QList<QSslError> &errors);
Q_SIGNALS:
void sslErrors(const QList<QSslError> &errors);
@@ -140,12 +146,13 @@ Q_SIGNALS:
void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
void headerChanged();
void dataReadProgress(int done, int total);
- void dataSendProgress(int done, int total);
+ void dataSendProgress(qint64 done, qint64 total);
private:
Q_DECLARE_PRIVATE(QHttpNetworkReply)
friend class QHttpNetworkConnection;
friend class QHttpNetworkConnectionPrivate;
+ friend class QHttpNetworkConnectionChannel;
};
@@ -158,18 +165,27 @@ public:
bool parseStatus(const QByteArray &status);
qint64 readHeader(QAbstractSocket *socket);
void parseHeader(const QByteArray &header);
- qint64 readBody(QAbstractSocket *socket, QIODevice *out);
+ qint64 readBody(QAbstractSocket *socket, QByteDataBuffer *out);
+ qint64 readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb);
bool findChallenge(bool forProxy, QByteArray &challenge) const;
QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const;
void clear();
- qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size);
- qint64 transferChunked(QIODevice *in, QIODevice *out);
+ qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size);
+ qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out);
qint64 getChunkSize(QIODevice *in, qint64 *chunkSize);
+ void appendUncompressedReplyData(QByteArray &qba);
+ void appendUncompressedReplyData(QByteDataBuffer &data);
+ void appendCompressedReplyData(QByteDataBuffer &data);
+
+ bool shouldEmitSignals();
+ bool expectContent();
+ void eraseData();
+
qint64 bytesAvailable() const;
bool isChunked();
- bool connectionCloseEnabled();
+ bool isConnectionCloseEnabled();
bool isGzipped();
#ifndef QT_NO_COMPRESS
bool gzipCheckHeader(QByteArray &content, int &pos);
@@ -194,7 +210,9 @@ public:
qint64 bodyLength;
qint64 contentRead;
qint64 totalProgress;
- QByteArray fragment;
+ QByteArray fragment; // used for header, status, chunk header etc, not for reply data
+ bool chunkedTransferEncoding;
+ bool connectionCloseEnabled;
qint64 currentChunkSize;
qint64 currentChunkRead;
QPointer<QHttpNetworkConnection> connection;
@@ -205,11 +223,11 @@ public:
#endif
bool autoDecompress;
- QByteArray responseData; // uncompressed body
+ QByteDataBuffer responseData; // uncompressed body
QByteArray compressedData; // compressed body (temporary)
- QBuffer requestDataBuffer;
- bool requestIsBuffering;
bool requestIsPrepared;
+
+ bool pipeliningUsed;
};
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index 7e5f03d..566b611 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qhttpnetworkrequest_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#ifndef QT_NO_HTTP
@@ -47,8 +48,8 @@ QT_BEGIN_NAMESPACE
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
- : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0),
- autoDecompress(false)
+ : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
+ autoDecompress(false), pipeliningAllowed(false)
{
}
@@ -57,8 +58,9 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest
{
operation = other.operation;
priority = other.priority;
- data = other.data;
+ uploadByteDevice = other.uploadByteDevice;
autoDecompress = other.autoDecompress;
+ pipeliningAllowed = other.pipeliningAllowed;
}
QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate()
@@ -69,7 +71,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot
{
return QHttpNetworkHeaderPrivate::operator==(other)
&& (operation == other.operation)
- && (data == other.data);
+ && (uploadByteDevice == other.uploadByteDevice);
}
QByteArray QHttpNetworkRequestPrivate::methodName() const
@@ -111,7 +113,7 @@ QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const
QUrl::FormattingOptions format(QUrl::RemoveFragment);
// for POST, query data is send as content
- if (operation == QHttpNetworkRequest::Post && !data)
+ if (operation == QHttpNetworkRequest::Post && !uploadByteDevice)
format |= QUrl::RemoveQuery;
// for requests through proxy, the Request-URI contains full url
if (throughProxy)
@@ -128,11 +130,11 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
{
QByteArray ba = request.d->methodName();
QByteArray uri = request.d->uri(throughProxy);
- ba += " " + uri;
+ ba += ' ' + uri;
QString majorVersion = QString::number(request.majorVersion());
QString minorVersion = QString::number(request.minorVersion());
- ba += " HTTP/" + majorVersion.toLatin1() + "." + minorVersion.toLatin1() + "\r\n";
+ ba += " HTTP/" + majorVersion.toLatin1() + '.' + minorVersion.toLatin1() + "\r\n";
QList<QPair<QByteArray, QByteArray> > fields = request.header();
QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
@@ -142,7 +144,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
// add content type, if not set in the request
if (request.headerField("content-type").isEmpty())
ba += "Content-Type: application/x-www-form-urlencoded\r\n";
- if (!request.d->data && request.d->url.hasQuery()) {
+ if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
QByteArray query = request.d->url.encodedQuery();
ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n";
ba += "\r\n";
@@ -238,14 +240,24 @@ void QHttpNetworkRequest::setPriority(Priority priority)
d->priority = priority;
}
-QIODevice *QHttpNetworkRequest::data() const
+bool QHttpNetworkRequest::isPipeliningAllowed() const
{
- return d->data;
+ return d->pipeliningAllowed;
}
-void QHttpNetworkRequest::setData(QIODevice *data)
+void QHttpNetworkRequest::setPipeliningAllowed(bool b)
{
- d->data = data;
+ d->pipeliningAllowed = b;
+}
+
+void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
+{
+ d->uploadByteDevice = bd;
+}
+
+QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const
+{
+ return d->uploadByteDevice;
}
int QHttpNetworkRequest::majorVersion() const
diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h
index 09be153..00eb5c9 100644
--- a/src/network/access/qhttpnetworkrequest_p.h
+++ b/src/network/access/qhttpnetworkrequest_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+class QNonContiguousByteDevice;
+
class QHttpNetworkRequestPrivate;
class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader
{
@@ -104,16 +106,19 @@ public:
Priority priority() const;
void setPriority(Priority priority);
- QIODevice *data() const;
- void setData(QIODevice *data);
+ bool isPipeliningAllowed() const;
+ void setPipeliningAllowed(bool b);
+
+ void setUploadByteDevice(QNonContiguousByteDevice *bd);
+ QNonContiguousByteDevice* uploadByteDevice() const;
private:
QSharedDataPointer<QHttpNetworkRequestPrivate> d;
friend class QHttpNetworkRequestPrivate;
friend class QHttpNetworkConnectionPrivate;
+ friend class QHttpNetworkConnectionChannel;
};
-
class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate
{
public:
@@ -129,8 +134,9 @@ public:
QHttpNetworkRequest::Operation operation;
QHttpNetworkRequest::Priority priority;
- mutable QIODevice *data;
+ mutable QNonContiguousByteDevice* uploadByteDevice;
bool autoDecompress;
+ bool pipeliningAllowed;
};
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 489f3c0..be7896b 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -50,6 +50,8 @@
#include "qnetworkaccesscachebackend_p.h"
#include "qabstractnetworkcache.h"
+#include "private/qnoncontiguousbytedevice_p.h"
+
QT_BEGIN_NAMESPACE
static bool factoryDataShutdown = false;
@@ -112,6 +114,36 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM
return 0;
}
+QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
+{
+ QNonContiguousByteDevice* device = 0;
+
+ if (reply->outgoingDataBuffer)
+ device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer);
+ else
+ device = QNonContiguousByteDeviceFactory::create(reply->outgoingData);
+
+ bool bufferDisallowed =
+ reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
+ QVariant(false)) == QVariant(true);
+ if (bufferDisallowed)
+ device->disableReset();
+
+ // make sure we delete this later
+ device->setParent(this);
+
+ connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64)));
+
+ return device;
+}
+
+// need to have this function since the reply is a private member variable
+// and the special backends need to access this.
+void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
+{
+ reply->emitUploadProgress(bytesSent, bytesTotal);
+}
+
QNetworkAccessBackend::QNetworkAccessBackend()
: manager(0)
, reply(0)
@@ -122,23 +154,24 @@ QNetworkAccessBackend::~QNetworkAccessBackend()
{
}
-void QNetworkAccessBackend::upstreamReadyRead()
+void QNetworkAccessBackend::downstreamReadyWrite()
{
// do nothing
}
-void QNetworkAccessBackend::downstreamReadyWrite()
+void QNetworkAccessBackend::copyFinished(QIODevice *)
{
// do nothing
}
-void QNetworkAccessBackend::copyFinished(QIODevice *)
+void QNetworkAccessBackend::ignoreSslErrors()
{
// do nothing
}
-void QNetworkAccessBackend::ignoreSslErrors()
+void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
{
+ Q_UNUSED(errors);
// do nothing
}
@@ -191,41 +224,19 @@ bool QNetworkAccessBackend::isCachingEnabled() const
return reply->isCachingEnabled();
}
-qint64 QNetworkAccessBackend::upstreamBytesAvailable() const
-{
- return reply->writeBuffer.size();
-}
-
-void QNetworkAccessBackend::upstreamBytesConsumed(qint64 count)
-{
- // remove count bytes from the write buffer
- reply->consume(count);
-}
-
-QByteArray QNetworkAccessBackend::readUpstream()
-{
- // ### this is expensive. Consider making QRingBuffer::peekAll keep the buffer it returns
- return reply->writeBuffer.peek(upstreamBytesAvailable());
-}
-
qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const
{
return reply->nextDownstreamBlockSize();
}
-qint64 QNetworkAccessBackend::downstreamBytesToConsume() const
-{
- return reply->writeBuffer.size();
-}
-
-void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data)
+void QNetworkAccessBackend::writeDownstreamData(QByteDataBuffer &list)
{
- reply->feed(data);
+ reply->appendDownstreamData(list);
}
void QNetworkAccessBackend::writeDownstreamData(QIODevice *data)
{
- reply->feed(data);
+ reply->appendDownstreamData(data);
}
QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 4330662..8fcbe65 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -70,6 +70,8 @@ class QNetworkAccessManagerPrivate;
class QNetworkReplyImplPrivate;
class QAbstractNetworkCache;
class QNetworkCacheMetaData;
+class QNetworkAccessBackendUploadIODevice;
+class QNonContiguousByteDevice;
// Should support direct file upload from disk or download to disk.
//
@@ -86,14 +88,13 @@ public:
// have different names. The Connection has two streams:
//
// - Upstream:
- // Upstream is data that is being written into this connection,
- // from the user. Upstream operates in a "pull" mechanism: the
- // connection will be notified that there is more data available
- // by a call to "upstreamReadyRead". The number of bytes
- // available is given by upstreamBytesAvailable(). A call to
- // readUpstream() always yields the entire upstream buffer. When
- // the connection has processed a certain amount of bytes from
- // that buffer, it should call upstreamBytesConsumed().
+ // The upstream uses a QNonContiguousByteDevice provided
+ // by the backend. This device emits the usual readyRead()
+ // signal when the backend has data available for the connection
+ // to write. The different backends can listen on this signal
+ // and then pull upload data from the QNonContiguousByteDevice and
+ // deal with it.
+ //
//
// - Downstream:
// Downstream is the data that is being read from this
@@ -111,15 +112,13 @@ public:
virtual void open() = 0;
virtual void closeDownstreamChannel() = 0;
- virtual void closeUpstreamChannel() = 0;
virtual bool waitForDownstreamReadyRead(int msecs) = 0;
- virtual bool waitForUpstreamBytesWritten(int msecs) = 0;
// slot-like:
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
virtual void copyFinished(QIODevice *);
virtual void ignoreSslErrors();
+ virtual void ignoreSslErrors(const QList<QSslError> &errors);
virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
virtual void setSslConfiguration(const QSslConfiguration &configuration);
@@ -155,18 +154,23 @@ public:
QVariant attribute(QNetworkRequest::Attribute code) const;
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
+ // return true if the QNonContiguousByteDevice of the upload
+ // data needs to support reset(). Currently needed for HTTP.
+ // This will possibly enable buffering of the upload data.
+ virtual bool needsResetableUploadData() {return false;};
+
protected:
- // these functions control the upstream mechanism
- // that is, data coming into the backend and out via the connection
- qint64 upstreamBytesAvailable() const;
- void upstreamBytesConsumed(qint64 count);
- QByteArray readUpstream();
+ // Create the device used for reading the upload data
+ QNonContiguousByteDevice* createUploadByteDevice();
+
// these functions control the downstream mechanism
// that is, data that has come via the connection and is going out the backend
qint64 nextDownstreamBlockSize() const;
- qint64 downstreamBytesToConsume() const;
- void writeDownstreamData(const QByteArray &data);
+ void writeDownstreamData(QByteDataBuffer &list);
+
+public slots:
+ // for task 251801, needs to be a slot to be called asynchronously
void writeDownstreamData(QIODevice *data);
protected slots:
@@ -179,10 +183,12 @@ protected slots:
void metaDataChanged();
void redirectionRequested(const QUrl &destination);
void sslErrors(const QList<QSslError> &errors);
+ void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
friend class QNetworkAccessManager;
friend class QNetworkAccessManagerPrivate;
+ friend class QNetworkAccessBackendUploadIODevice;
QNetworkAccessManagerPrivate *manager;
QNetworkReplyImplPrivate *reply;
};
diff --git a/src/network/access/qnetworkaccesscache.cpp b/src/network/access/qnetworkaccesscache.cpp
index 7f63f9a..26ffcf3 100644
--- a/src/network/access/qnetworkaccesscache.cpp
+++ b/src/network/access/qnetworkaccesscache.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qnetworkaccesscache_p.h b/src/network/access/qnetworkaccesscache_p.h
index 9e2ac93..6cf7ee8 100644
--- a/src/network/access/qnetworkaccesscache_p.h
+++ b/src/network/access/qnetworkaccesscache_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -64,6 +64,9 @@ QT_BEGIN_NAMESPACE
class QNetworkRequest;
class QUrl;
+// this class is not about caching files but about
+// caching objects used by QNetworkAccessManager, e.g. existing TCP connections
+// or credentials.
class QNetworkAccessCache: public QObject
{
Q_OBJECT
diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp
index d4a99e7..2be10db 100644
--- a/src/network/access/qnetworkaccesscachebackend.cpp
+++ b/src/network/access/qnetworkaccesscachebackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
QNetworkAccessCacheBackend::QNetworkAccessCacheBackend()
: QNetworkAccessBackend()
+ , device(0)
{
}
diff --git a/src/network/access/qnetworkaccesscachebackend_p.h b/src/network/access/qnetworkaccesscachebackend_p.h
index 3e3b5ea..70ae8b4 100644
--- a/src/network/access/qnetworkaccesscachebackend_p.h
+++ b/src/network/access/qnetworkaccesscachebackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qnetworkaccessdatabackend.cpp b/src/network/access/qnetworkaccessdatabackend.cpp
index e194b60..80a815f 100644
--- a/src/network/access/qnetworkaccessdatabackend.cpp
+++ b/src/network/access/qnetworkaccessdatabackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -117,7 +117,11 @@ void QNetworkAccessDataBackend::open()
setHeader(QNetworkRequest::ContentLengthHeader, payload.size());
emit metaDataChanged();
- writeDownstreamData(payload);
+ QByteDataBuffer list;
+ list.append(payload);
+ payload.clear(); // important because of implicit sharing!
+ writeDownstreamData(list);
+
finished();
return;
}
diff --git a/src/network/access/qnetworkaccessdatabackend_p.h b/src/network/access/qnetworkaccessdatabackend_p.h
index ba97241..ed54be0 100644
--- a/src/network/access/qnetworkaccessdatabackend_p.h
+++ b/src/network/access/qnetworkaccessdatabackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp
index d61deec..bbb9a45 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend.cpp
+++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -41,6 +41,8 @@
#include "qnetworkaccessdebugpipebackend_p.h"
#include "QtCore/qdatastream.h"
+#include <QCoreApplication>
+#include "private/qnoncontiguousbytedevice_p.h"
QT_BEGIN_NAMESPACE
@@ -51,12 +53,6 @@ enum {
WriteBufferSize = ReadBufferSize
};
-struct QNetworkAccessDebugPipeBackend::DataPacket
-{
- QList<QPair<QByteArray, QByteArray> > headers;
- QByteArray data;
-};
-
QNetworkAccessBackend *
QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
@@ -79,12 +75,14 @@ QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation o
}
QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend()
- : incomingPacketSize(0), bareProtocol(false)
+ : bareProtocol(false), hasUploadFinished(false), hasDownloadFinished(false),
+ hasEverythingFinished(false), bytesDownloaded(0), bytesUploaded(0)
{
}
QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend()
{
+ // this is signals disconnect, not network!
socket.disconnect(this); // we're not interested in the signals at this point
}
@@ -92,160 +90,154 @@ void QNetworkAccessDebugPipeBackend::open()
{
socket.connectToHost(url().host(), url().port(12345));
socket.setReadBufferSize(ReadBufferSize);
+
+ // socket ready read -> we can push from socket to downstream
connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
- connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError()));
connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
+ connect(&socket, SIGNAL(connected()), SLOT(socketConnected()));
+ // socket bytes written -> we can push more from upstream to socket
+ connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1");
- if (!bareProtocol) {
- // "Handshake":
- // send outgoing metadata and the URL being requested
- DataPacket packet;
- //packet.metaData = request().metaData();
- packet.data = url().toEncoded();
- send(packet);
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ uploadByteDevice = createUploadByteDevice();
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
}
}
-void QNetworkAccessDebugPipeBackend::closeDownstreamChannel()
+void QNetworkAccessDebugPipeBackend::socketReadyRead()
{
- if (operation() == QNetworkAccessManager::GetOperation)
- socket.disconnectFromHost();
+ pushFromSocketToDownstream();
}
-void QNetworkAccessDebugPipeBackend::closeUpstreamChannel()
+void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
{
- if (operation() == QNetworkAccessManager::PutOperation)
- socket.disconnectFromHost();
- else if (operation() == QNetworkAccessManager::PostOperation) {
- send(DataPacket());
- }
+ pushFromSocketToDownstream();
}
-bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
+void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
{
- readyReadEmitted = false;
- if (socket.bytesAvailable()) {
- socketReadyRead();
- if (readyReadEmitted)
- return true;
- }
- socket.waitForReadyRead(ms);
- return readyReadEmitted;
+ pushFromUpstreamToSocket();
}
-bool QNetworkAccessDebugPipeBackend::waitForUpstreamBytesWritten(int ms)
+void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot()
{
- bytesWrittenEmitted = false;
- upstreamReadyRead();
- if (bytesWrittenEmitted)
- return true;
-
- socket.waitForBytesWritten(ms);
- return bytesWrittenEmitted;
+ pushFromUpstreamToSocket();
}
-void QNetworkAccessDebugPipeBackend::upstreamReadyRead()
+void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream()
{
- int maxWrite = WriteBufferSize - socket.bytesToWrite();
- if (maxWrite <= 0)
- return; // can't write yet, wait for the socket to write
-
- if (bareProtocol) {
- QByteArray data = readUpstream();
- if (data.isEmpty())
- return;
+ QByteArray buffer;
- socket.write(data);
- upstreamBytesConsumed(data.size());
- bytesWrittenEmitted = true;
+ if (socket.state() == QAbstractSocket::ConnectingState) {
return;
}
- DataPacket packet;
- packet.data = readUpstream();
- if (packet.data.isEmpty())
- return; // we'll be called again when there's data
- if (packet.data.size() > maxWrite)
- packet.data.truncate(maxWrite);
-
- if (!send(packet)) {
- QString msg = QObject::tr("Write error writing to %1: %2")
- .arg(url().toString(), socket.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
+ forever {
+ if (hasDownloadFinished)
+ return;
- finished();
- return;
+ buffer.resize(ReadBufferSize);
+ qint64 haveRead = socket.read(buffer.data(), ReadBufferSize);
+
+ if (haveRead == -1) {
+ hasDownloadFinished = true;
+ // this ensures a good last downloadProgress is emitted
+ setHeader(QNetworkRequest::ContentLengthHeader, QVariant());
+ possiblyFinish();
+ break;
+ } else if (haveRead == 0) {
+ break;
+ } else {
+ // have read something
+ buffer.resize(haveRead);
+ bytesDownloaded += haveRead;
+
+ QByteDataBuffer list;
+ list.append(buffer);
+ buffer.clear(); // important because of implicit sharing!
+ writeDownstreamData(list);
+ }
}
- upstreamBytesConsumed(packet.data.size());
- bytesWrittenEmitted = true;
}
-void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
+void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket()
{
- socketReadyRead();
-}
+ // FIXME
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ if (hasUploadFinished)
+ return;
-void QNetworkAccessDebugPipeBackend::socketReadyRead()
-{
- if (bareProtocol) {
- qint64 bytesToRead = socket.bytesAvailable();
- if (bytesToRead) {
- QByteArray buffer;
- buffer.resize(bytesToRead);
- qint64 bytesRead = socket.read(buffer.data(), bytesToRead);
- if (bytesRead < bytesToRead)
- buffer.truncate(bytesRead);
- writeDownstreamData(buffer);
- readyReadEmitted = true;
+ forever {
+ if (socket.bytesToWrite() >= WriteBufferSize)
+ return;
+
+ qint64 haveRead;
+ const char *readPointer = uploadByteDevice->readPointer(WriteBufferSize, haveRead);
+ if (haveRead == -1) {
+ // EOF
+ hasUploadFinished = true;
+ emitReplyUploadProgress(bytesUploaded, bytesUploaded);
+ possiblyFinish();
+ break;
+ } else if (haveRead == 0 || readPointer == 0) {
+ // nothing to read right now, we will be called again later
+ break;
+ } else {
+ qint64 haveWritten;
+ haveWritten = socket.write(readPointer, haveRead);
+
+ if (haveWritten < 0) {
+ // write error!
+ QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2")
+ .arg(url().toString(), socket.errorString());
+ error(QNetworkReply::ProtocolFailure, msg);
+ finished();
+ return;
+ } else {
+ uploadByteDevice->advanceReadPointer(haveWritten);
+ bytesUploaded += haveWritten;
+ emitReplyUploadProgress(bytesUploaded, -1);
+ }
+
+ //QCoreApplication::processEvents();
+
+ }
}
- return;
}
+}
- while (canReceive() &&
- (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) {
- DataPacket packet;
- if (receive(packet)) {
- if (!packet.headers.isEmpty()) {
- QList<QPair<QByteArray, QByteArray> >::ConstIterator
- it = packet.headers.constBegin(),
- end = packet.headers.constEnd();
- for ( ; it != end; ++it)
- setRawHeader(it->first, it->second);
- metaDataChanged();
- }
+void QNetworkAccessDebugPipeBackend::possiblyFinish()
+{
+ if (hasEverythingFinished)
+ return;
+ hasEverythingFinished = true;
- if (!packet.data.isEmpty()) {
- writeDownstreamData(packet.data);
- readyReadEmitted = true;
- }
+ if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) {
+ socket.close();
+ finished();
+ } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) {
+ socket.close();
+ finished();
+ }
- if (packet.headers.isEmpty() && packet.data.isEmpty()) {
- // it's an eof
- socket.close();
- readyReadEmitted = true;
- }
- } else {
- // got an error
- QString msg = QObject::tr("Read error reading from %1: %2")
- .arg(url().toString(), socket.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
- finished();
- return;
- }
- }
}
-void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
+void QNetworkAccessDebugPipeBackend::closeDownstreamChannel()
{
- upstreamReadyRead();
+ qWarning() << "QNetworkAccessDebugPipeBackend::closeDownstreamChannel()" << operation();
+ //if (operation() == QNetworkAccessManager::GetOperation)
+ // socket.disconnectFromHost();
}
+
void QNetworkAccessDebugPipeBackend::socketError()
{
+ qWarning() << "QNetworkAccessDebugPipeBackend::socketError()" << socket.error();
QNetworkReply::NetworkError code;
switch (socket.error()) {
case QAbstractSocket::RemoteHostClosedError:
@@ -269,76 +261,28 @@ void QNetworkAccessDebugPipeBackend::socketError()
void QNetworkAccessDebugPipeBackend::socketDisconnected()
{
- socketReadyRead();
- if (incomingPacketSize == 0 && socket.bytesToWrite() == 0) {
+ pushFromSocketToDownstream();
+
+ if (socket.bytesToWrite() == 0) {
// normal close
- finished();
} else {
// abnormal close
QString msg = QObject::tr("Remote host closed the connection prematurely on %1")
.arg(url().toString());
error(QNetworkReply::RemoteHostClosedError, msg);
-
finished();
}
}
-bool QNetworkAccessDebugPipeBackend::send(const DataPacket &packet)
-{
- QByteArray ba;
- {
- QDataStream stream(&ba, QIODevice::WriteOnly);
- stream.setVersion(QDataStream::Qt_4_4);
-
- stream << packet.headers << packet.data;
- }
-
- qint32 outgoingPacketSize = ba.size();
- qint64 written = socket.write((const char*)&outgoingPacketSize, sizeof outgoingPacketSize);
- written += socket.write(ba);
- return quint64(written) == (outgoingPacketSize + sizeof outgoingPacketSize);
-}
-
-bool QNetworkAccessDebugPipeBackend::receive(DataPacket &packet)
+void QNetworkAccessDebugPipeBackend::socketConnected()
{
- if (!canReceive())
- return false;
-
- // canReceive() does the setting up for us
- Q_ASSERT(socket.bytesAvailable() >= incomingPacketSize);
- QByteArray incomingPacket = socket.read(incomingPacketSize);
- QDataStream stream(&incomingPacket, QIODevice::ReadOnly);
- stream.setVersion(QDataStream::Qt_4_4);
- stream >> packet.headers >> packet.data;
-
- // reset for next packet:
- incomingPacketSize = 0;
- socket.setReadBufferSize(ReadBufferSize);
- return true;
}
-bool QNetworkAccessDebugPipeBackend::canReceive()
+bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
{
- if (incomingPacketSize == 0) {
- // read the packet size
- if (quint64(socket.bytesAvailable()) >= sizeof incomingPacketSize)
- socket.read((char*)&incomingPacketSize, sizeof incomingPacketSize);
- else
- return false;
- }
-
- if (incomingPacketSize == 0) {
- QString msg = QObject::tr("Protocol error: packet of size 0 received");
- error(QNetworkReply::ProtocolFailure, msg);
- finished();
-
- socket.blockSignals(true);
- socket.abort();
- socket.blockSignals(false);
- return false;
- }
-
- return socket.bytesAvailable() >= incomingPacketSize;
+ Q_UNUSED(ms);
+ qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()");
+ return false;
}
#endif
diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h
index 5689343..8a1bad2 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend_p.h
+++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -66,35 +66,38 @@ class QNetworkAccessDebugPipeBackend: public QNetworkAccessBackend
{
Q_OBJECT
public:
- struct DataPacket;
QNetworkAccessDebugPipeBackend();
virtual ~QNetworkAccessDebugPipeBackend();
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
+protected:
+ void pushFromSocketToDownstream();
+ void pushFromUpstreamToSocket();
+ void possiblyFinish();
+ QNonContiguousByteDevice *uploadByteDevice;
+
private slots:
+ void uploadReadyReadSlot();
void socketReadyRead();
void socketBytesWritten(qint64 bytes);
void socketError();
void socketDisconnected();
+ void socketConnected();
private:
QTcpSocket socket;
- qint32 incomingPacketSize;
- bool readyReadEmitted;
- bool bytesWrittenEmitted;
bool bareProtocol;
+ bool hasUploadFinished;
+ bool hasDownloadFinished;
+ bool hasEverythingFinished;
- bool send(const DataPacket &packet);
- bool canReceive();
- bool receive(DataPacket &packet);
+ qint64 bytesDownloaded;
+ qint64 bytesUploaded;
};
class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory
diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp
index 86ebb73..60bff1c 100644
--- a/src/network/access/qnetworkaccessfilebackend.cpp
+++ b/src/network/access/qnetworkaccessfilebackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#include "qfileinfo.h"
#include "qurlinfo.h"
#include "qdir.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#include <QtCore/QCoreApplication>
@@ -77,7 +78,7 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op,
}
QNetworkAccessFileBackend::QNetworkAccessFileBackend()
- : totalBytes(0)
+ : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false)
{
}
@@ -108,7 +109,7 @@ void QNetworkAccessFileBackend::open()
QString fileName = url.toLocalFile();
if (fileName.isEmpty()) {
if (url.scheme() == QLatin1String("qrc"))
- fileName = QLatin1String(":") + url.path();
+ fileName = QLatin1Char(':') + url.path();
else
fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
}
@@ -126,6 +127,9 @@ void QNetworkAccessFileBackend::open()
break;
case QNetworkAccessManager::PutOperation:
mode = QIODevice::WriteOnly | QIODevice::Truncate;
+ uploadByteDevice = createUploadByteDevice();
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
break;
default:
Q_ASSERT_X(false, "QNetworkAccessFileBackend::open",
@@ -152,19 +156,50 @@ void QNetworkAccessFileBackend::open()
}
}
-void QNetworkAccessFileBackend::closeDownstreamChannel()
+void QNetworkAccessFileBackend::uploadReadyReadSlot()
{
- if (operation() == QNetworkAccessManager::GetOperation) {
- file.close();
- //downstreamChannelClosed();
+ if (hasUploadFinished)
+ return;
+
+ forever {
+ qint64 haveRead;
+ const char *readPointer = uploadByteDevice->readPointer(-1, haveRead);
+ if (haveRead == -1) {
+ // EOF
+ hasUploadFinished = true;
+ file.flush();
+ file.close();
+ finished();
+ break;
+ } else if (haveRead == 0 || readPointer == 0) {
+ // nothing to read right now, we will be called again later
+ break;
+ } else {
+ qint64 haveWritten;
+ haveWritten = file.write(readPointer, haveRead);
+
+ if (haveWritten < 0) {
+ // write error!
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
+ .arg(url().toString(), file.errorString());
+ error(QNetworkReply::ProtocolFailure, msg);
+
+ finished();
+ return;
+ } else {
+ uploadByteDevice->advanceReadPointer(haveWritten);
+ }
+
+
+ file.flush();
+ }
}
}
-void QNetworkAccessFileBackend::closeUpstreamChannel()
+void QNetworkAccessFileBackend::closeDownstreamChannel()
{
- if (operation() == QNetworkAccessManager::PutOperation) {
+ if (operation() == QNetworkAccessManager::GetOperation) {
file.close();
- finished();
}
}
@@ -174,40 +209,6 @@ bool QNetworkAccessFileBackend::waitForDownstreamReadyRead(int)
return readMoreFromFile();
}
-bool QNetworkAccessFileBackend::waitForUpstreamBytesWritten(int)
-{
- Q_ASSERT_X(false, "QNetworkAccessFileBackend::waitForUpstreamBytesWritten",
- "This function should never have been called, since there is never anything "
- "left to be written!");
- return false;
-}
-
-void QNetworkAccessFileBackend::upstreamReadyRead()
-{
- Q_ASSERT_X(operation() == QNetworkAccessManager::PutOperation, "QNetworkAccessFileBackend",
- "We're being told to upload data but operation isn't PUT!");
-
- // there's more data to be written to the file
- while (upstreamBytesAvailable()) {
- // write everything and let QFile handle it
- int written = file.write(readUpstream());
-
- if (written < 0) {
- // write error!
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
- .arg(url().toString(), file.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
-
- finished();
- return;
- }
-
- // successful write
- file.flush();
- upstreamBytesConsumed(written);
- }
-}
-
void QNetworkAccessFileBackend::downstreamReadyWrite()
{
Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend",
@@ -262,7 +263,11 @@ bool QNetworkAccessFileBackend::readMoreFromFile()
data.resize(actuallyRead);
totalBytes += actuallyRead;
- writeDownstreamData(data);
+
+ QByteDataBuffer list;
+ list.append(data);
+ data.clear(); // important because of implicit sharing!
+ writeDownstreamData(list);
}
return true;
}
diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h
index f731380..e5229f1 100644
--- a/src/network/access/qnetworkaccessfilebackend_p.h
+++ b/src/network/access/qnetworkaccessfilebackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -62,22 +62,25 @@ QT_BEGIN_NAMESPACE
class QNetworkAccessFileBackend: public QNetworkAccessBackend
{
+ Q_OBJECT
public:
QNetworkAccessFileBackend();
virtual ~QNetworkAccessFileBackend();
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
+public slots:
+ void uploadReadyReadSlot();
+protected:
+ QNonContiguousByteDevice *uploadByteDevice;
private:
QFile file;
qint64 totalBytes;
+ bool hasUploadFinished;
bool loadFileInfo();
bool readMoreFromFile();
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index f48989b..cc73577 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -42,6 +42,7 @@
#include "qnetworkaccessftpbackend_p.h"
#include "qnetworkaccessmanager_p.h"
#include "QtNetwork/qauthenticator.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#ifndef QT_NO_FTP
@@ -81,46 +82,11 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op,
return 0;
}
-class QNetworkAccessFtpIODevice: public QIODevice
-{
- //Q_OBJECT
-public:
- QNetworkAccessFtpBackend *backend;
- bool eof;
-
- inline QNetworkAccessFtpIODevice(QNetworkAccessFtpBackend *parent)
- : QIODevice(parent), backend(parent), eof(false)
- { open(ReadOnly); }
-
- bool isSequential() const { return true; }
- bool atEnd() const { return backend->upstreamBytesAvailable() == 0; }
-
- qint64 bytesAvailable() const { return backend->upstreamBytesAvailable(); }
- qint64 bytesToWrite() const { return backend->downstreamBytesToConsume(); }
-protected:
- qint64 readData(char *data, qint64 maxlen)
- {
- const QByteArray toSend = backend->readUpstream();
- maxlen = qMin<qint64>(maxlen, toSend.size());
- if (!maxlen)
- return eof ? -1 : 0;
-
- backend->upstreamBytesConsumed(maxlen);
- memcpy(data, toSend.constData(), maxlen);
- return maxlen;
- }
-
- qint64 writeData(const char *, qint64)
- { return -1; }
-
- friend class QNetworkAccessFtpBackend;
-};
-
-class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject
+class QNetworkAccessCachedFtpConnection: public QFtp, public QNetworkAccessCache::CacheableObject
{
// Q_OBJECT
public:
- QNetworkAccessFtpFtp()
+ QNetworkAccessCachedFtpConnection()
{
setExpires(true);
setShareable(false);
@@ -182,11 +148,11 @@ void QNetworkAccessFtpBackend::open()
}
state = LoggingIn;
- QNetworkAccessCache* cache = QNetworkAccessManagerPrivate::getCache(this);
+ QNetworkAccessCache* objectCache = QNetworkAccessManagerPrivate::getObjectCache(this);
QByteArray cacheKey = makeCacheKey(url);
- if (!cache->requestEntry(cacheKey, this,
+ if (!objectCache->requestEntry(cacheKey, this,
SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) {
- ftp = new QNetworkAccessFtpFtp;
+ ftp = new QNetworkAccessCachedFtpConnection;
#ifndef QT_NO_NETWORKPROXY
if (proxy.type() == QNetworkProxy::FtpCachingProxy)
ftp->setProxy(proxy.hostName(), proxy.port());
@@ -194,11 +160,15 @@ void QNetworkAccessFtpBackend::open()
ftp->connectToHost(url.host(), url.port(DefaultFtpPort));
ftp->login(url.userName(), url.password());
- cache->addEntry(cacheKey, ftp);
+ objectCache->addEntry(cacheKey, ftp);
ftpConnectionReady(ftp);
}
- uploadDevice = new QNetworkAccessFtpIODevice(this);
+ // Put operation
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice());
+ uploadDevice->setParent(this);
+ }
}
void QNetworkAccessFtpBackend::closeDownstreamChannel()
@@ -212,16 +182,6 @@ void QNetworkAccessFtpBackend::closeDownstreamChannel()
#endif
}
-void QNetworkAccessFtpBackend::closeUpstreamChannel()
-{
- if (operation() == QNetworkAccessManager::PutOperation) {
- Q_ASSERT(uploadDevice);
- uploadDevice->eof = true;
- if (!upstreamBytesAvailable())
- emit uploadDevice->readyRead();
- }
-}
-
bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
{
if (!ftp)
@@ -239,18 +199,6 @@ bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
return false;
}
-bool QNetworkAccessFtpBackend::waitForUpstreamBytesWritten(int ms)
-{
- Q_UNUSED(ms);
- qCritical("QNetworkAccess: FTP backend does not support waitForBytesWritten()");
- return false;
-}
-
-void QNetworkAccessFtpBackend::upstreamReadyRead()
-{
- // uh... how does QFtp operate?
-}
-
void QNetworkAccessFtpBackend::downstreamReadyWrite()
{
if (state == Transferring && ftp && ftp->bytesAvailable())
@@ -259,7 +207,7 @@ void QNetworkAccessFtpBackend::downstreamReadyWrite()
void QNetworkAccessFtpBackend::ftpConnectionReady(QNetworkAccessCache::CacheableObject *o)
{
- ftp = static_cast<QNetworkAccessFtpFtp *>(o);
+ ftp = static_cast<QNetworkAccessCachedFtpConnection *>(o);
connect(ftp, SIGNAL(done(bool)), SLOT(ftpDone()));
connect(ftp, SIGNAL(rawCommandReply(int,QString)), SLOT(ftpRawCommandReply(int,QString)));
connect(ftp, SIGNAL(readyRead()), SLOT(ftpReadyRead()));
@@ -279,7 +227,7 @@ void QNetworkAccessFtpBackend::disconnectFromFtp()
disconnect(ftp, 0, this, 0);
QByteArray key = makeCacheKey(url());
- QNetworkAccessManagerPrivate::getCache(this)->releaseEntry(key);
+ QNetworkAccessManagerPrivate::getObjectCache(this)->releaseEntry(key);
ftp = 0;
}
@@ -330,7 +278,7 @@ void QNetworkAccessFtpBackend::ftpDone()
// we're not connected, so remove the cache entry:
QByteArray key = makeCacheKey(url());
- QNetworkAccessManagerPrivate::getCache(this)->removeEntry(key);
+ QNetworkAccessManagerPrivate::getObjectCache(this)->removeEntry(key);
disconnect(ftp, 0, this, 0);
ftp->dispose();
@@ -407,7 +355,11 @@ void QNetworkAccessFtpBackend::ftpDone()
void QNetworkAccessFtpBackend::ftpReadyRead()
{
- writeDownstreamData(ftp->readAll());
+ QByteArray data = ftp->readAll();
+ QByteDataBuffer list;
+ list.append(data);
+ data.clear(); // important because of implicit sharing!
+ writeDownstreamData(list);
}
void QNetworkAccessFtpBackend::ftpRawCommandReply(int code, const QString &text)
diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h
index d2a8d35..03e37f6 100644
--- a/src/network/access/qnetworkaccessftpbackend_p.h
+++ b/src/network/access/qnetworkaccessftpbackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -66,7 +66,7 @@
QT_BEGIN_NAMESPACE
class QNetworkAccessFtpIODevice;
-class QNetworkAccessFtpFtp;
+class QNetworkAccessCachedFtpConnection;
class QNetworkAccessFtpBackend: public QNetworkAccessBackend
{
@@ -87,11 +87,8 @@ public:
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
void disconnectFromFtp();
@@ -104,8 +101,8 @@ public slots:
private:
friend class QNetworkAccessFtpIODevice;
- QPointer<QNetworkAccessFtpFtp> ftp;
- QNetworkAccessFtpIODevice *uploadDevice;
+ QPointer<QNetworkAccessCachedFtpConnection> ftp;
+ QIODevice *uploadDevice;
qint64 totalBytes;
int helpId, sizeId, mdtmId;
bool supportsSize, supportsMdtm;
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 0bc2a4b..60ba439 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -212,6 +212,7 @@ QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op,
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::HeadOperation:
case QNetworkAccessManager::PutOperation:
+ case QNetworkAccessManager::DeleteOperation:
break;
default:
@@ -244,6 +245,10 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const
code = QNetworkReply::ContentNotFoundError;
break;
+ case 405: // Method Not Allowed
+ code = QNetworkReply::ContentOperationNotPermittedError;
+ break;
+
case 407:
code = QNetworkReply::ProxyAuthenticationRequiredError;
break;
@@ -265,12 +270,12 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const
return code;
}
-class QNetworkAccessHttpBackendCache: public QHttpNetworkConnection,
+class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection,
public QNetworkAccessCache::CacheableObject
{
// Q_OBJECT
public:
- QNetworkAccessHttpBackendCache(const QString &hostName, quint16 port, bool encrypt)
+ QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt)
: QHttpNetworkConnection(hostName, port, encrypt)
{
setExpires(true);
@@ -286,41 +291,10 @@ public:
}
};
-class QNetworkAccessHttpBackendIODevice: public QIODevice
-{
- // Q_OBJECT
-public:
- bool eof;
- QNetworkAccessHttpBackendIODevice(QNetworkAccessHttpBackend *parent)
- : QIODevice(parent), eof(false)
- {
- setOpenMode(ReadOnly);
- }
- bool isSequential() const { return true; }
- qint64 bytesAvailable() const
- { return static_cast<QNetworkAccessHttpBackend *>(parent())->upstreamBytesAvailable(); }
-
-protected:
- virtual qint64 readData(char *buffer, qint64 maxlen)
- {
- qint64 ret = static_cast<QNetworkAccessHttpBackend *>(parent())->deviceReadData(buffer, maxlen);
- if (!ret && eof)
- return -1;
- return ret;
- }
-
- virtual qint64 writeData(const char *, qint64)
- {
- return -1; // cannot write
- }
-
- friend class QNetworkAccessHttpBackend;
-};
-
QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
: QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
#ifndef QT_NO_OPENSSL
- , pendingSslConfiguration(0), pendingIgnoreSslErrors(false)
+ , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
#endif
{
}
@@ -337,11 +311,15 @@ QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend()
void QNetworkAccessHttpBackend::disconnectFromHttp()
{
if (http) {
+ // This is abut disconnecting signals, not about disconnecting TCP connections
disconnect(http, 0, this, 0);
- QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this);
+
+ // Get the object cache that stores our QHttpNetworkConnection objects
+ QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
cache->releaseEntry(cacheKey);
}
+ // This is abut disconnecting signals, not about disconnecting TCP connections
if (httpReply)
disconnect(httpReply, 0, this, 0);
@@ -507,20 +485,24 @@ void QNetworkAccessHttpBackend::postRequest()
case QNetworkAccessManager::PostOperation:
invalidateCache();
httpRequest.setOperation(QHttpNetworkRequest::Post);
- uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
+ httpRequest.setUploadByteDevice(createUploadByteDevice());
break;
case QNetworkAccessManager::PutOperation:
invalidateCache();
httpRequest.setOperation(QHttpNetworkRequest::Put);
- uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
+ httpRequest.setUploadByteDevice(createUploadByteDevice());
+ break;
+
+ case QNetworkAccessManager::DeleteOperation:
+ invalidateCache();
+ httpRequest.setOperation(QHttpNetworkRequest::Delete);
break;
default:
break; // can't happen
}
- httpRequest.setData(uploadDevice);
httpRequest.setUrl(url());
QList<QByteArray> headers = request().rawHeaderList();
@@ -528,17 +510,23 @@ void QNetworkAccessHttpBackend::postRequest()
httpRequest.setHeaderField(header, request().rawHeader(header));
if (loadedFromCache) {
- QNetworkAccessBackend::finished();
+ // commented this out since it will be called later anyway
+ // by copyFinished()
+ //QNetworkAccessBackend::finished();
return; // no need to send the request! :)
}
+ if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
+ httpRequest.setPipeliningAllowed(true);
+
httpReply = http->sendRequest(httpRequest);
httpReply->setParent(this);
#ifndef QT_NO_OPENSSL
if (pendingSslConfiguration)
httpReply->setSslConfiguration(*pendingSslConfiguration);
- if (pendingIgnoreSslErrors)
+ if (pendingIgnoreAllSslErrors)
httpReply->ignoreSslErrors();
+ httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList);
#endif
connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead()));
@@ -602,16 +590,20 @@ void QNetworkAccessHttpBackend::open()
// check if we have an open connection to this host
cacheKey = makeCacheKey(this, theProxy);
- QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this);
- if ((http = static_cast<QNetworkAccessHttpBackendCache *>(cache->requestEntryNow(cacheKey))) == 0) {
+ QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
+ // the http object is actually a QHttpNetworkConnection
+ http = static_cast<QNetworkAccessCachedHttpConnection *>(cache->requestEntryNow(cacheKey));
+ if (http == 0) {
// no entry in cache; create an object
- http = new QNetworkAccessHttpBackendCache(url.host(), url.port(), encrypt);
+ // the http object is actually a QHttpNetworkConnection
+ http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt);
#ifndef QT_NO_NETWORKPROXY
http->setTransparentProxy(transparentProxy);
http->setCacheProxy(cacheProxy);
#endif
+ // cache the QHttpNetworkConnection corresponding to this cache key
cache->addEntry(cacheKey, http);
}
@@ -624,18 +616,6 @@ void QNetworkAccessHttpBackend::closeDownstreamChannel()
// this indicates that the user closed the stream while the reply isn't finished yet
}
-void QNetworkAccessHttpBackend::closeUpstreamChannel()
-{
- // this indicates that the user finished uploading the data for POST
- Q_ASSERT(uploadDevice);
-
- if (uploadDevice->eof)
- return; // received a 2nd time. should fix 257662 and 256369
-
- uploadDevice->eof = true;
- emit uploadDevice->readChannelFinished();
-}
-
bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs)
{
Q_ASSERT(http);
@@ -655,38 +635,6 @@ bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs)
return false;
}
-bool QNetworkAccessHttpBackend::waitForUpstreamBytesWritten(int msecs)
-{
-
- // ### FIXME: not implemented in QHttpNetworkAccess
- Q_UNUSED(msecs);
- qCritical("QNetworkAccess: HTTP backend does not support waitForBytesWritten()");
- return false;
-}
-
-void QNetworkAccessHttpBackend::upstreamReadyRead()
-{
- // There is more data available from the user to be uploaded
- // QHttpNetworkAccess implements the upload rate control:
- // we simply tell QHttpNetworkAccess that there is more data available
- // it'll pull from us when it can (through uploadDevice)
-
- Q_ASSERT(uploadDevice);
- emit uploadDevice->readyRead();
-}
-
-qint64 QNetworkAccessHttpBackend::deviceReadData(char *buffer, qint64 maxlen)
-{
- QByteArray toBeUploaded = readUpstream();
- if (toBeUploaded.isEmpty())
- return 0; // nothing to be uploaded
-
- maxlen = qMin<qint64>(maxlen, toBeUploaded.length());
-
- memcpy(buffer, toBeUploaded.constData(), maxlen);
- upstreamBytesConsumed(maxlen);
- return maxlen;
-}
void QNetworkAccessHttpBackend::downstreamReadyWrite()
{
@@ -705,16 +653,19 @@ void QNetworkAccessHttpBackend::readFromHttp()
if (!httpReply)
return;
- // We implement the download rate control
- // Don't read from QHttpNetworkAccess more than QNetworkAccessBackend wants
- // One of the two functions above will be called when we can read again
+ // We read possibly more than nextDownstreamBlockSize(), but
+ // this is not a critical thing since it is already in the
+ // memory anyway
- qint64 bytesToRead = qBound<qint64>(0, httpReply->bytesAvailable(), nextDownstreamBlockSize());
- if (!bytesToRead)
- return;
+ QByteDataBuffer list;
+
+ while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) {
+ QByteArray data = httpReply->readAny();
+ list.append(data);
+ }
- QByteArray data = httpReply->read(bytesToRead);
- writeDownstreamData(data);
+ if (!list.isEmpty())
+ writeDownstreamData(list);
}
void QNetworkAccessHttpBackend::replyFinished()
@@ -736,10 +687,15 @@ void QNetworkAccessHttpBackend::replyFinished()
// store the SSL configuration now
// once we call finished(), we won't have access to httpReply anymore
QSslConfiguration sslConfig = httpReply->sslConfiguration();
- if (pendingSslConfiguration)
+ if (pendingSslConfiguration) {
*pendingSslConfiguration = sslConfig;
- else if (!sslConfig.isNull())
- pendingSslConfiguration = new QSslConfiguration(sslConfig);
+ } else if (!sslConfig.isNull()) {
+ QT_TRY {
+ pendingSslConfiguration = new QSslConfiguration(sslConfig);
+ } QT_CATCH(...) {
+ qWarning("QNetworkAccess: could not allocate a QSslConfiguration object for a SSL connection.");
+ }
+ }
#endif
finished();
@@ -765,6 +721,8 @@ void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode)
void QNetworkAccessHttpBackend::replyHeaderChanged()
{
+ setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, httpReply->isPipeliningUsed());
+
// reconstruct the HTTP header
QList<QPair<QByteArray, QByteArray> > headerMap = httpReply->header();
QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(),
@@ -908,7 +866,14 @@ bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &m
checkForRedirect(status);
- writeDownstreamData(contents);
+ emit metaDataChanged();
+
+ // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads
+ // see task 250221 / 251801
+ qRegisterMetaType<QIODevice*>("QIODevice*");
+ QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
+
+
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes";
#endif
@@ -929,7 +894,18 @@ void QNetworkAccessHttpBackend::ignoreSslErrors()
if (httpReply)
httpReply->ignoreSslErrors();
else
- pendingIgnoreSslErrors = true;
+ pendingIgnoreAllSslErrors = true;
+}
+
+void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ if (httpReply) {
+ httpReply->ignoreSslErrors(errors);
+ } else {
+ // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+ // is called before QNetworkAccessManager::get() (or post(), etc.)
+ pendingIgnoreSslErrorsList = errors;
+ }
}
void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const
@@ -975,6 +951,12 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo
if (hop_by_hop)
continue;
+ // Do not copy over the Date header because it will be
+ // different for every request and therefore cause a re-write to
+ // the disk when a 304 is received inside replyHeaderChanged()
+ if (header == "date")
+ continue;
+
// Don't store Warning 1xx headers
if (header == "warning") {
QByteArray v = rawHeader(header);
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 1e3fa6a..e5a6045 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -66,7 +66,7 @@
QT_BEGIN_NAMESPACE
-class QNetworkAccessHttpBackendCache;
+class QNetworkAccessCachedHttpConnection;
class QNetworkAccessHttpBackendIODevice;
@@ -79,15 +79,13 @@ public:
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
virtual void copyFinished(QIODevice *);
#ifndef QT_NO_OPENSSL
virtual void ignoreSslErrors();
+ virtual void ignoreSslErrors(const QList<QSslError> &errors);
virtual void fetchSslConfiguration(QSslConfiguration &configuration) const;
virtual void setSslConfiguration(const QSslConfiguration &configuration);
@@ -96,6 +94,9 @@ public:
qint64 deviceReadData(char *buffer, qint64 maxlen);
+ // we return true since HTTP needs to send PUT/POST data again after having authenticated
+ bool needsResetableUploadData() {return true;};
+
private slots:
void replyReadyRead();
void replyFinished();
@@ -106,12 +107,14 @@ private slots:
private:
QHttpNetworkReply *httpReply;
- QPointer<QNetworkAccessHttpBackendCache> http;
+ QPointer<QNetworkAccessCachedHttpConnection> http;
QByteArray cacheKey;
- QNetworkAccessHttpBackendIODevice *uploadDevice;
+ QNetworkAccessBackendUploadIODevice *uploadDevice;
+
#ifndef QT_NO_OPENSSL
QSslConfiguration *pendingSslConfiguration;
- bool pendingIgnoreSslErrors;
+ bool pendingIgnoreAllSslErrors;
+ QList<QSslError> pendingIgnoreSslErrorsList;
#endif
void disconnectFromHttp();
@@ -122,8 +125,6 @@ private:
void postRequest();
void readFromHttp();
void checkForRedirect(const int statusCode);
-
- friend class QNetworkAccessHttpBackendIODevice;
};
class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 2369f31..2b2504f 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -149,6 +149,9 @@ static void ensureInitialized()
\value PostOperation send the contents of an HTML form for
processing via HTTP POST (created with post())
+ \value DeleteOperation delete contents operation (created with
+ deleteResource())
+
\omitvalue UnknownOperation
\sa QNetworkReply::operation()
@@ -303,6 +306,7 @@ static QByteArray proxyAuthenticationKey(const QNetworkProxy &proxy, const QStri
case QNetworkProxy::FtpCachingProxy:
key.setScheme(QLatin1String("proxy-ftp"));
+ break;
case QNetworkProxy::DefaultProxy:
case QNetworkProxy::NoProxy:
@@ -542,10 +546,10 @@ void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
}
/*!
- This function is used to post a request to obtain the network
- headers for \a request. It takes its name after the HTTP request
- associated (HEAD). It returns a new QNetworkReply object which
- will contain such headers.
+ Posts a request to obtain the network headers for \a request
+ and returns a new QNetworkReply object which will contain such headers
+
+ The function is named after the HTTP request associated (HEAD).
*/
QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
{
@@ -553,13 +557,14 @@ QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
}
/*!
- This function is used to post a request to obtain the contents of
- the target \a request. It will cause the contents to be
- downloaded, along with the headers associated with it. It returns
- a new QNetworkReply object opened for reading which emits its
- QIODevice::readyRead() signal whenever new data arrives.
+ Posts a request to obtain the contents of the target \a request
+ and returns a new QNetworkReply object opened for reading which emits the
+ \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
+ arrives.
- \sa post(), put()
+ The contents as well as associated headers will be downloaded.
+
+ \sa post(), put(), deleteResource()
*/
QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
{
@@ -567,21 +572,18 @@ QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
}
/*!
- This function is used to send an HTTP POST request to the
- destination specified by \a request. The contents of the \a data
+ Sends an HTTP POST request to the destination specified by \a request
+ and returns a new QNetworkReply object opened for reading that will
+ contain the reply sent by the server. The contents of the \a data
device will be uploaded to the server.
- \a data must be opened for reading when this function is called
- and must remain valid until the finished() signal is emitted for
- this reply.
-
- The returned QNetworkReply object will be open for reading and
- will contain the reply sent by the server to the POST request.
+ \a data must be open for reading and must remain valid until the
+ finished() signal is emitted for this reply.
- \note sending a POST request on protocols other than HTTP and
+ \note Sending a POST request on protocols other than HTTP and
HTTPS is undefined and will probably fail.
- \sa get(), put()
+ \sa get(), put(), deleteResource()
*/
QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
{
@@ -590,8 +592,9 @@ QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODe
/*!
\overload
- This function sends the contents of the \a data byte array to the
- destination specified by \a request.
+
+ Sends the contents of the \a data byte array to the destination
+ specified by \a request.
*/
QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
{
@@ -605,20 +608,19 @@ QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const
}
/*!
- This function is used to upload the contents of \a data to the
- destination \a request.
+ Uploads the contents of \a data to the destination \a request and
+ returnes a new QNetworkReply object that will be open for reply.
\a data must be opened for reading when this function is called
and must remain valid until the finished() signal is emitted for
this reply.
- The returned QNetworkReply object will be open for reply, but
- whether anything will be available for reading is protocol
- dependent. For HTTP, the server may send a small HTML page
- indicating the upload was successful (or not). Other protocols
- will probably have content in their replies.
+ Whether anything will be available for reading from the returned
+ object is protocol dependent. For HTTP, the server may send a
+ small HTML page indicating the upload was successful (or not).
+ Other protocols will probably have content in their replies.
- For HTTP, this request will send a PUT request, which most servers
+ \note For HTTP, this request will send a PUT request, which most servers
do not allow. Form upload mechanisms, including that of uploading
files through HTML forms, use the POST mechanism.
@@ -631,8 +633,8 @@ QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODev
/*!
\overload
- This function sends the contents of the \a data byte array to the
- destination specified by \a request.
+ Sends the contents of the \a data byte array to the destination
+ specified by \a request.
*/
QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
{
@@ -646,6 +648,21 @@ QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const
}
/*!
+ \since 4.6
+
+ Sends a request to delete the resource identified by the URL of \a request.
+
+ \note This feature is currently available for HTTP only, performing an
+ HTTP DELETE request.
+
+ \sa get(), post(), put()
+*/
+QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
+{
+ return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
+}
+
+/*!
Returns a new QNetworkReply object to handle the operation \a op
and request \a req. The device \a outgoingData is always 0 for Get and
Head requests, but is the value passed to post() and put() in
@@ -690,15 +707,15 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
priv->urlForLastAuthentication = url;
}
- // third step: setup the reply
+ // third step: find a backend
+ priv->backend = d->findBackend(op, request);
+
+ // fourth step: setup the reply
priv->setup(op, request, outgoingData);
#ifndef QT_NO_NETWORKPROXY
QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
priv->proxyList = proxyList;
#endif
-
- // fourth step: find a backend
- priv->backend = d->findBackend(op, request);
if (priv->backend) {
priv->backend->setParent(reply);
priv->backend->reply = priv;
@@ -749,8 +766,8 @@ void QNetworkAccessManagerPrivate::createCookieJar() const
if (!cookieJarCreated) {
// keep the ugly hack in here
QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
- that->cookieJarCreated = true;
that->cookieJar = new QNetworkCookieJar(that->q_func());
+ that->cookieJarCreated = true;
}
}
@@ -785,7 +802,13 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBac
QAuthenticator *authenticator)
{
Q_Q(QNetworkAccessManager);
-
+ // ### FIXME Tracking of successful authentications
+ // This code is a bit broken right now for SOCKS authentication
+ // first request: proxyAuthenticationRequired gets emitted, credentials gets saved
+ // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true,
+ // proxyAuthenticationRequired gets emitted again
+ // possible solution: some tracking inside the authenticator
+ // or a new function proxyAuthenticationSucceeded(true|false)
if (proxy != backend->reply->lastProxyAuthentication) {
QNetworkAuthenticationCredential *cred = fetchCachedCredentials(proxy);
if (cred) {
@@ -820,7 +843,7 @@ void QNetworkAccessManagerPrivate::addCredentials(const QNetworkProxy &p,
QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
auth->insert(QString(), authenticator->user(), authenticator->password());
- cache.addEntry(cacheKey, auth); // replace the existing one, if there's any
+ objectCache.addEntry(cacheKey, auth); // replace the existing one, if there's any
if (realm.isEmpty()) {
break;
@@ -854,13 +877,13 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QNetworkProxy &p,
QByteArray cacheKey = proxyAuthenticationKey(proxy, realm);
if (cacheKey.isEmpty())
return 0;
- if (!cache.hasEntry(cacheKey))
+ if (!objectCache.hasEntry(cacheKey))
return 0;
QNetworkAuthenticationCache *auth =
- static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
+ static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
QNetworkAuthenticationCredential *cred = auth->findClosestMatch(QString());
- cache.releaseEntry(cacheKey);
+ objectCache.releaseEntry(cacheKey);
// proxy cache credentials always have exactly one item
Q_ASSERT_X(cred, "QNetworkAccessManager",
@@ -901,15 +924,15 @@ void QNetworkAccessManagerPrivate::addCredentials(const QUrl &url,
copy.setUserName(authenticator->user());
do {
QByteArray cacheKey = authenticationKey(copy, realm);
- if (cache.hasEntry(cacheKey)) {
+ if (objectCache.hasEntry(cacheKey)) {
QNetworkAuthenticationCache *auth =
- static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
+ static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
auth->insert(domain, authenticator->user(), authenticator->password());
- cache.releaseEntry(cacheKey);
+ objectCache.releaseEntry(cacheKey);
} else {
QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
auth->insert(domain, authenticator->user(), authenticator->password());
- cache.addEntry(cacheKey, auth);
+ objectCache.addEntry(cacheKey, auth);
}
if (copy.userName().isEmpty()) {
@@ -943,19 +966,19 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QUrl &url,
realm = authentication->realm();
QByteArray cacheKey = authenticationKey(url, realm);
- if (!cache.hasEntry(cacheKey))
+ if (!objectCache.hasEntry(cacheKey))
return 0;
QNetworkAuthenticationCache *auth =
- static_cast<QNetworkAuthenticationCache *>(cache.requestEntryNow(cacheKey));
+ static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path());
- cache.releaseEntry(cacheKey);
+ objectCache.releaseEntry(cacheKey);
return cred;
}
void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
{
- manager->d_func()->cache.clear();
+ manager->d_func()->objectCache.clear();
}
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index ed392f7..09664d0 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -74,6 +74,7 @@ public:
GetOperation,
PutOperation,
PostOperation,
+ DeleteOperation,
UnknownOperation = 0
};
@@ -100,6 +101,7 @@ public:
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
+ QNetworkReply *deleteResource(const QNetworkRequest &request);
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 0417f93..356bc33 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -98,10 +98,12 @@ public:
QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
+ // this is the cache for storing downloaded files
QAbstractNetworkCache *networkCache;
+
QNetworkCookieJar *cookieJar;
- QNetworkAccessCache cache;
+
#ifndef QT_NO_NETWORKPROXY
QNetworkProxy proxy;
QNetworkProxyFactory *proxyFactory;
@@ -109,8 +111,12 @@ public:
bool cookieJarCreated;
- static inline QNetworkAccessCache *getCache(QNetworkAccessBackend *backend)
- { return &backend->manager->cache; }
+
+ // this cache can be used by individual backends to cache e.g. their TCP connections to a server
+ // and use the connections for multiple requests.
+ QNetworkAccessCache objectCache;
+ static inline QNetworkAccessCache *getObjectCache(QNetworkAccessBackend *backend)
+ { return &backend->manager->objectCache; }
Q_AUTOTEST_EXPORT static void clearCache(QNetworkAccessManager *manager);
Q_DECLARE_PUBLIC(QNetworkAccessManager)
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index 3e55251..f6eddd3 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -504,7 +504,12 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const
}
if (!d->domain.isEmpty()) {
result += "; domain=";
- result += QUrl::toAce(d->domain);
+ QString domainNoDot = d->domain;
+ if (domainNoDot.startsWith(QLatin1Char('.'))) {
+ result += '.';
+ domainNoDot = domainNoDot.mid(1);
+ }
+ result += QUrl::toAce(domainNoDot);
}
if (!d->path.isEmpty()) {
result += "; path=";
@@ -1026,264 +1031,9 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QNetworkCookie &cookie)
{
- s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ")";
+ s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
return s.space();
}
#endif
-
-
-class QNetworkCookieJarPrivate: public QObjectPrivate
-{
-public:
- QList<QNetworkCookie> allCookies;
-
- Q_DECLARE_PUBLIC(QNetworkCookieJar)
-};
-
-/*!
- \class QNetworkCookieJar
- \brief The QNetworkCookieJar class implements a simple jar of QNetworkCookie objects
- \since 4.4
-
- Cookies are small bits of information that stateless protocols
- like HTTP use to maintain some persistent information across
- requests.
-
- A cookie is set by a remote server when it replies to a request
- and it expects the same cookie to be sent back when further
- requests are sent.
-
- The cookie jar is the object that holds all cookies set in
- previous requests. Web browsers save their cookie jars to disk in
- order to conserve permanent cookies across invocations of the
- application.
-
- QNetworkCookieJar does not implement permanent storage: it only
- keeps the cookies in memory. Once the QNetworkCookieJar object is
- deleted, all cookies it held will be discarded as well. If you
- want to save the cookies, you should derive from this class and
- implement the saving to disk to your own storage format.
-
- This class implements only the basic security recommended by the
- cookie specifications and does not implement any cookie acceptance
- policy (it accepts all cookies set by any requests). In order to
- override those rules, you should reimplement the
- cookiesForUrl() and setCookiesFromUrl() virtual
- functions. They are called by QNetworkReply and
- QNetworkAccessManager when they detect new cookies and when they
- require cookies.
-
- \sa QNetworkCookie, QNetworkAccessManager, QNetworkReply,
- QNetworkRequest, QNetworkAccessManager::setCookieJar()
-*/
-
-/*!
- Creates a QNetworkCookieJar object and sets the parent object to
- be \a parent.
-
- The cookie jar is initialized to empty.
-*/
-QNetworkCookieJar::QNetworkCookieJar(QObject *parent)
- : QObject(*new QNetworkCookieJarPrivate, parent)
-{
-}
-
-/*!
- Destroys this cookie jar object and discards all cookies stored in
- it. Cookies are not saved to disk in the QNetworkCookieJar default
- implementation.
-
- If you need to save the cookies to disk, you have to derive from
- QNetworkCookieJar and save the cookies to disk yourself.
-*/
-QNetworkCookieJar::~QNetworkCookieJar()
-{
-}
-
-/*!
- Returns all cookies stored in this cookie jar. This function is
- suitable for derived classes to save cookies to disk, as well as
- to implement cookie expiration and other policies.
-
- \sa setAllCookies(), cookiesForUrl()
-*/
-QList<QNetworkCookie> QNetworkCookieJar::allCookies() const
-{
- return d_func()->allCookies;
-}
-
-/*!
- Sets the internal list of cookies held by this cookie jar to be \a
- cookieList. This function is suitable for derived classes to
- implement loading cookies from permanent storage, or their own
- cookie acceptance policies by reimplementing
- setCookiesFromUrl().
-
- \sa allCookies(), setCookiesFromUrl()
-*/
-void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
-{
- Q_D(QNetworkCookieJar);
- d->allCookies = cookieList;
-}
-
-static inline bool isParentPath(QString path, QString reference)
-{
- if (!path.endsWith(QLatin1Char('/')))
- path += QLatin1Char('/');
- if (!reference.endsWith(QLatin1Char('/')))
- reference += QLatin1Char('/');
- return path.startsWith(reference);
-}
-
-static inline bool isParentDomain(QString domain, QString reference)
-{
- if (!reference.startsWith(QLatin1Char('.')))
- return domain == reference;
-
- return domain.endsWith(reference) || domain == reference.mid(1);
-}
-
-/*!
- Adds the cookies in the list \a cookieList to this cookie
- jar. Default values for path and domain are taken from the \a
- url object.
-
- Returns true if one or more cookes are set for url otherwise false.
-
- If a cookie already exists in the cookie jar, it will be
- overridden by those in \a cookieList.
-
- The default QNetworkCookieJar class implements only a very basic
- security policy (it makes sure that the cookies' domain and path
- match the reply's). To enhance the security policy with your own
- algorithms, override setCookiesFromUrl().
-
- Also, QNetworkCookieJar does not have a maximum cookie jar
- size. Reimplement this function to discard older cookies to create
- room for new ones.
-
- \sa cookiesForUrl(), QNetworkAccessManager::setCookieJar()
-*/
-bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList,
- const QUrl &url)
-{
- Q_D(QNetworkCookieJar);
- QString defaultDomain = url.host();
- QString pathAndFileName = url.path();
- QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
- if (defaultPath.isEmpty())
- defaultPath = QLatin1Char('/');
-
- int added = 0;
- QDateTime now = QDateTime::currentDateTime();
- foreach (QNetworkCookie cookie, cookieList) {
- bool isDeletion = !cookie.isSessionCookie() &&
- cookie.expirationDate() < now;
-
- // validate the cookie & set the defaults if unset
- if (cookie.path().isEmpty())
- cookie.setPath(defaultPath);
- else if (!isParentPath(pathAndFileName, cookie.path()))
- continue; // not accepted
-
- if (cookie.domain().isEmpty()) {
- cookie.setDomain(defaultDomain);
- } else {
- QString domain = cookie.domain();
- if (!(isParentDomain(domain, defaultDomain)
- || isParentDomain(defaultDomain, domain))) {
- continue; // not accepted
- }
-
- // reject if domain is like ".com"
- // (i.e., reject if domain does not contain embedded dots, see RFC 2109 section 4.3.2)
- // this is just a rudimentary check and does not cover all cases
- if (domain.lastIndexOf(QLatin1Char('.')) == 0)
- continue; // not accepted
-
- }
-
- QList<QNetworkCookie>::Iterator it = d->allCookies.begin(),
- end = d->allCookies.end();
- for ( ; it != end; ++it)
- // does this cookie already exist?
- if (cookie.name() == it->name() &&
- cookie.domain() == it->domain() &&
- cookie.path() == it->path()) {
- // found a match
- d->allCookies.erase(it);
- break;
- }
-
- // did not find a match
- if (!isDeletion) {
- d->allCookies += cookie;
- ++added;
- }
- }
- return (added > 0);
-}
-
-/*!
- Returns the cookies to be added to when a request is sent to
- \a url. This function is called by the default
- QNetworkAccessManager::createRequest(), which adds the
- cookies returned by this function to the request being sent.
-
- If more than one cookie with the same name is found, but with
- differing paths, the one with longer path is returned before the
- one with shorter path. In other words, this function returns
- cookies sorted by path length.
-
- The default QNetworkCookieJar class implements only a very basic
- security policy (it makes sure that the cookies' domain and path
- match the reply's). To enhance the security policy with your own
- algorithms, override cookiesForUrl().
-
- \sa setCookiesFromUrl(), QNetworkAccessManager::setCookieJar()
-*/
-QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const
-{
-// \b Warning! This is only a dumb implementation!
-// It does NOT follow all of the recommendations from
-// http://wp.netscape.com/newsref/std/cookie_spec.html
-// It does not implement a very good cross-domain verification yet.
-
- Q_D(const QNetworkCookieJar);
- QDateTime now = QDateTime::currentDateTime();
- QList<QNetworkCookie> result;
-
- // scan our cookies for something that matches
- QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(),
- end = d->allCookies.constEnd();
- for ( ; it != end; ++it) {
- if (!isParentDomain(url.host(), it->domain()))
- continue;
- if (!isParentPath(url.path(), it->path()))
- continue;
- if (!(*it).isSessionCookie() && (*it).expirationDate() < now)
- continue;
-
- // insert this cookie into result, sorted by path
- QList<QNetworkCookie>::Iterator insertIt = result.begin();
- while (insertIt != result.end()) {
- if (insertIt->path().length() < it->path().length()) {
- // insert here
- insertIt = result.insert(insertIt, *it);
- break;
- } else {
- ++insertIt;
- }
- }
-
- // this is the shortest path yet, just append
- if (insertIt == result.end())
- result += *it;
- }
-
- return result;
-}
-
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h
index b1b4480..d5f51e9 100644
--- a/src/network/access/qnetworkcookie.h
+++ b/src/network/access/qnetworkcookie.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -106,26 +106,6 @@ private:
};
Q_DECLARE_TYPEINFO(QNetworkCookie, Q_MOVABLE_TYPE);
-class QNetworkCookieJarPrivate;
-class Q_NETWORK_EXPORT QNetworkCookieJar: public QObject
-{
- Q_OBJECT
-public:
- QNetworkCookieJar(QObject *parent = 0);
- virtual ~QNetworkCookieJar();
-
- virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
- virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
-
-protected:
- QList<QNetworkCookie> allCookies() const;
- void setAllCookies(const QList<QNetworkCookie> &cookieList);
-
-private:
- Q_DECLARE_PRIVATE(QNetworkCookieJar)
- Q_DISABLE_COPY(QNetworkCookieJar)
-};
-
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QNetworkCookie &);
@@ -133,6 +113,9 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QNetworkCookie &);
QT_END_NAMESPACE
+// ### Qt5 remove this include
+#include "qnetworkcookiejar.h"
+
Q_DECLARE_METATYPE(QNetworkCookie)
Q_DECLARE_METATYPE(QList<QNetworkCookie>)
diff --git a/src/network/access/qnetworkcookie_p.h b/src/network/access/qnetworkcookie_p.h
index ffea34b..fb4c0f1 100644
--- a/src/network/access/qnetworkcookie_p.h
+++ b/src/network/access/qnetworkcookie_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp
new file mode 100644
index 0000000..e2c1975
--- /dev/null
+++ b/src/network/access/qnetworkcookiejar.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkcookiejar.h"
+#include "qnetworkcookiejar_p.h"
+
+#include "QtNetwork/qnetworkcookie.h"
+#include "QtCore/qurl.h"
+#include "QtCore/qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNetworkCookieJar
+ \brief The QNetworkCookieJar class implements a simple jar of QNetworkCookie objects
+ \since 4.4
+
+ Cookies are small bits of information that stateless protocols
+ like HTTP use to maintain some persistent information across
+ requests.
+
+ A cookie is set by a remote server when it replies to a request
+ and it expects the same cookie to be sent back when further
+ requests are sent.
+
+ The cookie jar is the object that holds all cookies set in
+ previous requests. Web browsers save their cookie jars to disk in
+ order to conserve permanent cookies across invocations of the
+ application.
+
+ QNetworkCookieJar does not implement permanent storage: it only
+ keeps the cookies in memory. Once the QNetworkCookieJar object is
+ deleted, all cookies it held will be discarded as well. If you
+ want to save the cookies, you should derive from this class and
+ implement the saving to disk to your own storage format.
+
+ This class implements only the basic security recommended by the
+ cookie specifications and does not implement any cookie acceptance
+ policy (it accepts all cookies set by any requests). In order to
+ override those rules, you should reimplement the
+ cookiesForUrl() and setCookiesFromUrl() virtual
+ functions. They are called by QNetworkReply and
+ QNetworkAccessManager when they detect new cookies and when they
+ require cookies.
+
+ \sa QNetworkCookie, QNetworkAccessManager, QNetworkReply,
+ QNetworkRequest, QNetworkAccessManager::setCookieJar()
+*/
+
+/*!
+ Creates a QNetworkCookieJar object and sets the parent object to
+ be \a parent.
+
+ The cookie jar is initialized to empty.
+*/
+QNetworkCookieJar::QNetworkCookieJar(QObject *parent)
+ : QObject(*new QNetworkCookieJarPrivate, parent)
+{
+}
+
+/*!
+ Destroys this cookie jar object and discards all cookies stored in
+ it. Cookies are not saved to disk in the QNetworkCookieJar default
+ implementation.
+
+ If you need to save the cookies to disk, you have to derive from
+ QNetworkCookieJar and save the cookies to disk yourself.
+*/
+QNetworkCookieJar::~QNetworkCookieJar()
+{
+}
+
+/*!
+ Returns all cookies stored in this cookie jar. This function is
+ suitable for derived classes to save cookies to disk, as well as
+ to implement cookie expiration and other policies.
+
+ \sa setAllCookies(), cookiesForUrl()
+*/
+QList<QNetworkCookie> QNetworkCookieJar::allCookies() const
+{
+ return d_func()->allCookies;
+}
+
+/*!
+ Sets the internal list of cookies held by this cookie jar to be \a
+ cookieList. This function is suitable for derived classes to
+ implement loading cookies from permanent storage, or their own
+ cookie acceptance policies by reimplementing
+ setCookiesFromUrl().
+
+ \sa allCookies(), setCookiesFromUrl()
+*/
+void QNetworkCookieJar::setAllCookies(const QList<QNetworkCookie> &cookieList)
+{
+ Q_D(QNetworkCookieJar);
+ d->allCookies = cookieList;
+}
+
+static inline bool isParentPath(QString path, QString reference)
+{
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ if (!reference.endsWith(QLatin1Char('/')))
+ reference += QLatin1Char('/');
+ return path.startsWith(reference);
+}
+
+static inline bool isParentDomain(QString domain, QString reference)
+{
+ if (!reference.startsWith(QLatin1Char('.')))
+ return domain == reference;
+
+ return domain.endsWith(reference) || domain == reference.mid(1);
+}
+
+/*!
+ Adds the cookies in the list \a cookieList to this cookie
+ jar. Default values for path and domain are taken from the \a
+ url object.
+
+ Returns true if one or more cookes are set for url otherwise false.
+
+ If a cookie already exists in the cookie jar, it will be
+ overridden by those in \a cookieList.
+
+ The default QNetworkCookieJar class implements only a very basic
+ security policy (it makes sure that the cookies' domain and path
+ match the reply's). To enhance the security policy with your own
+ algorithms, override setCookiesFromUrl().
+
+ Also, QNetworkCookieJar does not have a maximum cookie jar
+ size. Reimplement this function to discard older cookies to create
+ room for new ones.
+
+ \sa cookiesForUrl(), QNetworkAccessManager::setCookieJar()
+*/
+bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList,
+ const QUrl &url)
+{
+ Q_D(QNetworkCookieJar);
+ QString defaultDomain = url.host();
+ QString pathAndFileName = url.path();
+ QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1);
+ if (defaultPath.isEmpty())
+ defaultPath = QLatin1Char('/');
+
+ int added = 0;
+ QDateTime now = QDateTime::currentDateTime();
+ foreach (QNetworkCookie cookie, cookieList) {
+ bool isDeletion = !cookie.isSessionCookie() &&
+ cookie.expirationDate() < now;
+
+ // validate the cookie & set the defaults if unset
+ if (cookie.path().isEmpty())
+ cookie.setPath(defaultPath);
+ else if (!isParentPath(pathAndFileName, cookie.path()))
+ continue; // not accepted
+
+ if (cookie.domain().isEmpty()) {
+ cookie.setDomain(defaultDomain);
+ } else {
+ QString domain = cookie.domain();
+ if (!(isParentDomain(domain, defaultDomain)
+ || isParentDomain(defaultDomain, domain))) {
+ continue; // not accepted
+ }
+
+ // reject if domain is like ".com"
+ // (i.e., reject if domain does not contain embedded dots, see RFC 2109 section 4.3.2)
+ // this is just a rudimentary check and does not cover all cases
+ if (domain.lastIndexOf(QLatin1Char('.')) == 0)
+ continue; // not accepted
+
+ }
+
+ QList<QNetworkCookie>::Iterator it = d->allCookies.begin(),
+ end = d->allCookies.end();
+ for ( ; it != end; ++it)
+ // does this cookie already exist?
+ if (cookie.name() == it->name() &&
+ cookie.domain() == it->domain() &&
+ cookie.path() == it->path()) {
+ // found a match
+ d->allCookies.erase(it);
+ break;
+ }
+
+ // did not find a match
+ if (!isDeletion) {
+ d->allCookies += cookie;
+ ++added;
+ }
+ }
+ return (added > 0);
+}
+
+/*!
+ Returns the cookies to be added to when a request is sent to
+ \a url. This function is called by the default
+ QNetworkAccessManager::createRequest(), which adds the
+ cookies returned by this function to the request being sent.
+
+ If more than one cookie with the same name is found, but with
+ differing paths, the one with longer path is returned before the
+ one with shorter path. In other words, this function returns
+ cookies sorted by path length.
+
+ The default QNetworkCookieJar class implements only a very basic
+ security policy (it makes sure that the cookies' domain and path
+ match the reply's). To enhance the security policy with your own
+ algorithms, override cookiesForUrl().
+
+ \sa setCookiesFromUrl(), QNetworkAccessManager::setCookieJar()
+*/
+QList<QNetworkCookie> QNetworkCookieJar::cookiesForUrl(const QUrl &url) const
+{
+// \b Warning! This is only a dumb implementation!
+// It does NOT follow all of the recommendations from
+// http://wp.netscape.com/newsref/std/cookie_spec.html
+// It does not implement a very good cross-domain verification yet.
+
+ Q_D(const QNetworkCookieJar);
+ QDateTime now = QDateTime::currentDateTime();
+ QList<QNetworkCookie> result;
+
+ // scan our cookies for something that matches
+ QList<QNetworkCookie>::ConstIterator it = d->allCookies.constBegin(),
+ end = d->allCookies.constEnd();
+ for ( ; it != end; ++it) {
+ if (!isParentDomain(url.host(), it->domain()))
+ continue;
+ if (!isParentPath(url.path(), it->path()))
+ continue;
+ if (!(*it).isSessionCookie() && (*it).expirationDate() < now)
+ continue;
+
+ // insert this cookie into result, sorted by path
+ QList<QNetworkCookie>::Iterator insertIt = result.begin();
+ while (insertIt != result.end()) {
+ if (insertIt->path().length() < it->path().length()) {
+ // insert here
+ insertIt = result.insert(insertIt, *it);
+ break;
+ } else {
+ ++insertIt;
+ }
+ }
+
+ // this is the shortest path yet, just append
+ if (insertIt == result.end())
+ result += *it;
+ }
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h
new file mode 100644
index 0000000..294ee16
--- /dev/null
+++ b/src/network/access/qnetworkcookiejar.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCOOKIEJAR_H
+#define QNETWORKCOOKIEJAR_H
+
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+
+// ### Qt5 remove this include
+#include "qnetworkcookie.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+class QNetworkCookieJarPrivate;
+class Q_NETWORK_EXPORT QNetworkCookieJar: public QObject
+{
+ Q_OBJECT
+public:
+ QNetworkCookieJar(QObject *parent = 0);
+ virtual ~QNetworkCookieJar();
+
+ virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
+ virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
+
+protected:
+ QList<QNetworkCookie> allCookies() const;
+ void setAllCookies(const QList<QNetworkCookie> &cookieList);
+
+private:
+ Q_DECLARE_PRIVATE(QNetworkCookieJar)
+ Q_DISABLE_COPY(QNetworkCookieJar)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/network/access/qnetworkcookiejar_p.h b/src/network/access/qnetworkcookiejar_p.h
new file mode 100644
index 0000000..b1e36d5
--- /dev/null
+++ b/src/network/access/qnetworkcookiejar_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCOOKIEJAR_P_H
+#define QNETWORKCOOKIEJAR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Network Access framework. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "qnetworkcookie.h"
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkCookieJarPrivate: public QObjectPrivate
+{
+public:
+ QList<QNetworkCookie> allCookies;
+
+ Q_DECLARE_PUBLIC(QNetworkCookieJar)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index e78611a..1985186 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -41,8 +41,11 @@
//#define QNETWORKDISKCACHE_DEBUG
+#ifndef QT_NO_NETWORKDISKCACHE
+
#include "qnetworkdiskcache.h"
#include "qnetworkdiskcache_p.h"
+#include "QtCore/qscopedpointer.h"
#include <qfile.h>
#include <qdir.h>
@@ -79,6 +82,20 @@ QT_BEGIN_NAMESPACE
use on the system to 50MB.
Note you have to set the cache directory before it will work.
+
+ A network disk cache can be enabled by:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 0
+
+ When sending requests, to control the preference of when to use the cache
+ and when to use the network, consider the following:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 1
+
+ To check whether the response came from the cache or from the network, the
+ following can be applied:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp 2
*/
/*!
@@ -180,8 +197,7 @@ QIODevice *QNetworkDiskCache::prepare(const QNetworkCacheMetaData &metaData)
break;
}
}
-
- QCacheItem *cacheItem = new QCacheItem;
+ QScopedPointer<QCacheItem> cacheItem(new QCacheItem);
cacheItem->metaData = metaData;
QIODevice *device = 0;
@@ -190,16 +206,20 @@ QIODevice *QNetworkDiskCache::prepare(const QNetworkCacheMetaData &metaData)
device = &(cacheItem->data);
} else {
QString templateName = d->tmpCacheFileName();
- cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
- if (!cacheItem->file->open()) {
+ QT_TRY {
+ cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
+ } QT_CATCH(...) {
+ cacheItem->file = 0;
+ }
+ if (!cacheItem->file || !cacheItem->file->open()) {
qWarning() << "QNetworkDiskCache::prepare() unable to open temporary file";
- delete cacheItem;
+ cacheItem.reset();
return 0;
}
cacheItem->writeHeader(cacheItem->file);
device = cacheItem->file;
}
- d->inserting[device] = cacheItem;
+ d->inserting[device] = cacheItem.take();
return device;
}
@@ -358,31 +378,28 @@ QIODevice *QNetworkDiskCache::data(const QUrl &url)
qDebug() << "QNetworkDiskCache::data()" << url;
#endif
Q_D(QNetworkDiskCache);
- QBuffer *buffer = 0;
+ QScopedPointer<QBuffer> buffer;
if (!url.isValid())
- return buffer;
+ return 0;
if (d->lastItem.metaData.url() == url && d->lastItem.data.isOpen()) {
- buffer = new QBuffer;
+ buffer.reset(new QBuffer);
buffer->setData(d->lastItem.data.data());
} else {
- QFile *file = new QFile(d->cacheFileName(url));
- if (!file->open(QFile::ReadOnly | QIODevice::Unbuffered)) {
- delete file;
+ QScopedPointer<QFile> file(new QFile(d->cacheFileName(url)));
+ if (!file->open(QFile::ReadOnly | QIODevice::Unbuffered))
return 0;
- }
- if (!d->lastItem.read(file, true)) {
+
+ if (!d->lastItem.read(file.data(), true)) {
file->close();
remove(url);
- delete file;
return 0;
}
if (d->lastItem.data.isOpen()) {
// compressed
- buffer = new QBuffer;
+ buffer.reset(new QBuffer);
buffer->setData(d->lastItem.data.data());
- delete file;
} else {
- buffer = new QBuffer;
+ buffer.reset(new QBuffer);
// ### verify that QFile uses the fd size and not the file name
qint64 size = file->size() - file->pos();
const uchar *p = 0;
@@ -390,16 +407,15 @@ QIODevice *QNetworkDiskCache::data(const QUrl &url)
p = file->map(file->pos(), size);
#endif
if (p) {
- file->setParent(buffer);
buffer->setData((const char *)p, size);
+ file.take()->setParent(buffer.data());
} else {
buffer->setData(file->readAll());
- delete file;
}
}
}
buffer->open(QBuffer::ReadOnly);
- return buffer;
+ return buffer.take();
}
/*!
@@ -669,3 +685,5 @@ bool QCacheItem::read(QFile *device, bool readData)
}
QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKDISKCACHE
diff --git a/src/network/access/qnetworkdiskcache.h b/src/network/access/qnetworkdiskcache.h
index d533107..318c924 100644
--- a/src/network/access/qnetworkdiskcache.h
+++ b/src/network/access/qnetworkdiskcache.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Network)
+#ifndef QT_NO_NETWORKDISKCACHE
+
class QNetworkDiskCachePrivate;
class Q_NETWORK_EXPORT QNetworkDiskCache : public QAbstractNetworkCache
{
@@ -86,9 +88,10 @@ private:
Q_DISABLE_COPY(QNetworkDiskCache)
};
+#endif // QT_NO_NETWORKDISKCACHE
+
QT_END_NAMESPACE
QT_END_HEADER
#endif // QNETWORKDISKCACHE_H
-
diff --git a/src/network/access/qnetworkdiskcache_p.h b/src/network/access/qnetworkdiskcache_p.h
index 0f3d6d2..4f4ed3d 100644
--- a/src/network/access/qnetworkdiskcache_p.h
+++ b/src/network/access/qnetworkdiskcache_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index b64fe94..4720041 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -154,6 +154,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
authentication to serve the content but the credentials provided
were not accepted (if any)
+ \value ContentReSendError the request needed to be sent
+ again, but this failed for example because the upload data
+ could not be read a second time.
+
\value ProtocolUnknownError the Network Access API cannot
honor the request because the protocol is not known
@@ -447,6 +451,31 @@ QNetworkReply::NetworkError QNetworkReply::error() const
}
/*!
+ \since 4.6
+
+ Returns true when the reply has finished or was aborted.
+
+ \sa isRunning()
+*/
+bool QNetworkReply::isFinished() const
+{
+ return d_func()->isFinished();
+}
+
+/*!
+ \since 4.6
+
+ Returns true when the request is still processing and the
+ reply has not finished or was aborted yet.
+
+ \sa isFinished()
+*/
+bool QNetworkReply::isRunning() const
+{
+ return !isFinished();
+}
+
+/*!
Returns the URL of the content downloaded or uploaded. Note that
the URL may be different from that of the original request.
@@ -564,6 +593,38 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
}
}
+
+/*!
+ \overload
+ \since 4.6
+
+ If this function is called, the SSL errors given in \a errors
+ will be ignored.
+
+ Note that you can set the expected certificate in the SSL error:
+ If, for instance, you want to issue a request to a server that uses
+ a self-signed certificate, consider the following snippet:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkreply.cpp 0
+
+ Multiple calls to this function will replace the list of errors that
+ were passed in previous calls.
+ You can clear the list of errors you want to ignore by calling this
+ function with an empty list.
+
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
+*/
+void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ // do this cryptic trick, because we could not add a virtual method to this class later on
+ // since that breaks binary compatibility
+ int id = metaObject()->indexOfMethod("ignoreSslErrorsImplementation(QList<QSslError>)");
+ if (id != -1) {
+ QList<QSslError> copy(errors);
+ void *arr[] = { 0, &copy };
+ qt_metacall(QMetaObject::InvokeMetaMethod, id, arr);
+ }
+}
#endif
/*!
@@ -578,7 +639,7 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
sslErrors() signal, which indicates which errors were
found.
- \sa sslConfiguration(), sslErrors()
+ \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
*/
void QNetworkReply::ignoreSslErrors()
{
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 6a3c73f..89cd42a 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -92,6 +92,7 @@ public:
ContentOperationNotPermittedError,
ContentNotFoundError,
AuthenticationRequiredError,
+ ContentReSendError,
UnknownContentError = 299,
// protocol errors
@@ -115,6 +116,8 @@ public:
QNetworkAccessManager::Operation operation() const;
QNetworkRequest request() const;
NetworkError error() const;
+ bool isFinished() const;
+ bool isRunning() const;
QUrl url() const;
// "cooked" headers
@@ -131,6 +134,7 @@ public:
#ifndef QT_NO_OPENSSL
QSslConfiguration sslConfiguration() const;
void setSslConfiguration(const QSslConfiguration &configuration);
+ void ignoreSslErrors(const QList<QSslError> &errors);
#endif
public Q_SLOTS:
diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h
index f7dd4ef..1b9ade7 100644
--- a/src/network/access/qnetworkreply_p.h
+++ b/src/network/access/qnetworkreply_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -75,6 +75,8 @@ public:
static inline void setManager(QNetworkReply *reply, QNetworkAccessManager *manager)
{ reply->d_func()->manager = manager; }
+ virtual bool isFinished() const { return false; }
+
Q_DECLARE_PUBLIC(QNetworkReply)
};
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 29bf238..a60a8dd 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,13 +46,14 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qdatetime.h"
#include "QtNetwork/qsslconfiguration.h"
+#include "qnetworkaccesshttpbackend_p.h"
#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
- : backend(0), outgoingData(0),
+ : backend(0), outgoingData(0), outgoingDataBuffer(0),
copyDevice(0),
cacheEnabled(false), cacheSaveDevice(0),
notificationHandlingPaused(false),
@@ -64,8 +65,13 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
void QNetworkReplyImplPrivate::_q_startOperation()
{
- // This function is called exactly once
+ // ensure this function is only being called once
+ if (state == Working) {
+ qDebug("QNetworkReplyImpl::_q_startOperation was called more than once");
+ return;
+ }
state = Working;
+
if (!backend) {
error(QNetworkReplyImpl::ProtocolUnknownError,
QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!;
@@ -77,60 +83,11 @@ void QNetworkReplyImplPrivate::_q_startOperation()
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
pendingNotifications.append(NotifyDownstreamReadyWrite);
- if (outgoingData) {
- _q_sourceReadyRead();
-#if 0 // ### FIXME
- if (outgoingData->atEndOfStream() && writeBuffer.isEmpty())
- // empty upload
- emit q->uploadProgress(0, 0);
-#endif
- }
handleNotifications();
}
}
-void QNetworkReplyImplPrivate::_q_sourceReadyRead()
-{
- if (state != Working)
- return;
-
- // read data from the outgoingData QIODevice into our internal buffer
- enum { DesiredBufferSize = 32 * 1024 };
-
- if (writeBuffer.size() >= DesiredBufferSize)
- return; // don't grow the buffer too much
-
- // read as many bytes are available or up until we fill up the buffer
- // but always read at least one byte
- qint64 bytesToRead = qBound<qint64>(1, outgoingData->bytesAvailable(),
- DesiredBufferSize - writeBuffer.size());
- char *ptr = writeBuffer.reserve(bytesToRead);
- qint64 bytesActuallyRead = outgoingData->read(ptr, bytesToRead);
- if (bytesActuallyRead == -1) {
- // EOF
- writeBuffer.chop(bytesToRead);
- backendNotify(NotifyCloseUpstreamChannel);
- return;
- }
-
- if (bytesActuallyRead < bytesToRead)
- writeBuffer.chop(bytesToRead - bytesActuallyRead);
-
- // if we did read anything, let the backend know and handle it
- if (bytesActuallyRead)
- backendNotify(NotifyUpstreamReadyRead);
-
- // check for EOF again
- if (!outgoingData->isSequential() && outgoingData->atEnd())
- backendNotify(NotifyCloseUpstreamChannel);
-}
-
-void QNetworkReplyImplPrivate::_q_sourceReadChannelFinished()
-{
- _q_sourceReadyRead();
-}
-
void QNetworkReplyImplPrivate::_q_copyReadyRead()
{
Q_Q(QNetworkReplyImpl);
@@ -146,19 +103,21 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
break;
bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
- char *ptr = readBuffer.reserve(bytesToRead);
- qint64 bytesActuallyRead = copyDevice->read(ptr, bytesToRead);
+ QByteArray byteData;
+ byteData.resize(bytesToRead);
+ qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size());
if (bytesActuallyRead == -1) {
- readBuffer.chop(bytesToRead);
+ byteData.clear();
backendNotify(NotifyCopyFinished);
- return;
+ break;
}
- if (bytesActuallyRead != bytesToRead)
- readBuffer.chop(bytesToRead - bytesActuallyRead);
+ byteData.resize(bytesActuallyRead);
+ readBuffer.append(byteData);
if (!copyDevice->isSequential() && copyDevice->atEnd()) {
backendNotify(NotifyCopyFinished);
+ bytesDownloaded += bytesActuallyRead;
break;
}
@@ -184,6 +143,67 @@ void QNetworkReplyImplPrivate::_q_copyReadChannelFinished()
_q_copyReadyRead();
}
+void QNetworkReplyImplPrivate::_q_bufferOutgoingDataFinished()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ // make sure this is only called once, ever.
+ //_q_bufferOutgoingData may call it or the readChannelFinished emission
+ if (state != Buffering)
+ return;
+
+ // disconnect signals
+ QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+
+ // finally, start the request
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+}
+
+void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ if (!outgoingDataBuffer) {
+ // first call, create our buffer
+ outgoingDataBuffer = new QRingBuffer();
+
+ QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+ }
+
+ qint64 bytesBuffered = 0;
+ qint64 bytesToBuffer = 0;
+
+ // read data into our buffer
+ forever {
+ bytesToBuffer = outgoingData->bytesAvailable();
+ // unknown? just try 2 kB, this also ensures we always try to read the EOF
+ if (bytesToBuffer <= 0)
+ bytesToBuffer = 2*1024;
+
+ char *dst = outgoingDataBuffer->reserve(bytesToBuffer);
+ bytesBuffered = outgoingData->read(dst, bytesToBuffer);
+
+ if (bytesBuffered == -1) {
+ // EOF has been reached.
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ _q_bufferOutgoingDataFinished();
+ break;
+ } else if (bytesBuffered == 0) {
+ // nothing read right now, just wait until we get called again
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ break;
+ } else {
+ // don't break, try to read() again
+ outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered);
+ }
+ }
+}
+
+
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
@@ -194,13 +214,42 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
url = request.url();
operation = op;
- if (outgoingData) {
- q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead()));
- q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished()));
+ if (outgoingData && backend) {
+ // there is data to be uploaded, e.g. HTTP POST.
+
+ if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) {
+ // backend does not need upload buffering or
+ // fixed size non-sequential
+ // just start the operation
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ } else {
+ bool bufferingDisallowed =
+ req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
+ false).toBool();
+
+ if (bufferingDisallowed) {
+ // if a valid content-length header for the request was supplied, we can disable buffering
+ // if not, we will buffer anyway
+ if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) {
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ } else {
+ state = Buffering;
+ QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ } else {
+ // _q_startOperation will be called when the buffering has finished.
+ state = Buffering;
+ QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ }
+ } else {
+ // No outgoing data (e.g. HTTP GET request)
+ // or no backend
+ // if no backend, _q_startOperation will handle the error of this
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
q->QIODevice::open(QIODevice::ReadOnly);
- QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
void QNetworkReplyImplPrivate::backendNotify(InternalNotifications notification)
@@ -234,18 +283,10 @@ void QNetworkReplyImplPrivate::handleNotifications()
backend->downstreamReadyWrite();
break;
- case NotifyUpstreamReadyRead:
- backend->upstreamReadyRead();
- break;
-
case NotifyCloseDownstreamChannel:
backend->closeDownstreamChannel();
break;
- case NotifyCloseUpstreamChannel:
- backend->closeUpstreamChannel();
- break;
-
case NotifyCopyFinished: {
QIODevice *dev = copyDevice;
copyDevice = 0;
@@ -334,49 +375,33 @@ void QNetworkReplyImplPrivate::completeCacheSave()
cacheEnabled = false;
}
-void QNetworkReplyImplPrivate::consume(qint64 count)
+void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
Q_Q(QNetworkReplyImpl);
- if (count <= 0) {
- qWarning("QNetworkConnection: backend signalled that it consumed %ld bytes", long(count));
- return;
- }
-
- if (outgoingData)
- // schedule another read from the source
- QMetaObject::invokeMethod(q_func(), "_q_sourceReadyRead", Qt::QueuedConnection);
-
- writeBuffer.skip(count);
- if (bytesUploaded == -1)
- bytesUploaded = count;
- else
- bytesUploaded += count;
-
- QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader);
+ bytesUploaded = bytesSent;
pauseNotificationHandling();
- emit q->uploadProgress(bytesUploaded,
- totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+ emit q->uploadProgress(bytesSent, bytesTotal);
resumeNotificationHandling();
}
+
qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
{
enum { DesiredBufferSize = 32 * 1024 };
if (readBufferMaxSize == 0)
return DesiredBufferSize;
- return qMax<qint64>(0, readBufferMaxSize - readBuffer.size());
+ return qMax<qint64>(0, readBufferMaxSize - readBuffer.byteAmount());
}
-void QNetworkReplyImplPrivate::feed(const QByteArray &data)
+// we received downstream data and send this to the cache
+// and to our readBuffer (which in turn gets read by the user of QNetworkReply)
+void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
{
Q_Q(QNetworkReplyImpl);
if (!q->isOpen())
return;
- char *ptr = readBuffer.reserve(data.size());
- memcpy(ptr, data.constData(), data.size());
-
if (cacheEnabled && !cacheSaveDevice) {
// save the meta data
QNetworkCacheMetaData metaData;
@@ -405,10 +430,19 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data)
}
}
- if (cacheSaveDevice)
- cacheSaveDevice->write(data);
+ qint64 bytesWritten = 0;
+ for (int i = 0; i < data.bufferCount(); i++) {
+ QByteArray item = data[i];
+
+ if (cacheSaveDevice)
+ cacheSaveDevice->write(item.constData(), item.size());
+ readBuffer.append(item);
- bytesDownloaded += data.size();
+ bytesWritten += item.size();
+ }
+ data.clear();
+
+ bytesDownloaded += bytesWritten;
lastBytesDownloaded = bytesDownloaded;
QPointer<QNetworkReplyImpl> qq = q;
@@ -417,6 +451,8 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data)
pauseNotificationHandling();
emit q->downloadProgress(bytesDownloaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+ // important: At the point of this readyRead(), the data parameter list must be empty,
+ // else implicit sharing will trigger memcpy when the user is reading data!
emit q->readyRead();
// hopefully we haven't been deleted here
@@ -428,7 +464,8 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data)
}
}
-void QNetworkReplyImplPrivate::feed(QIODevice *data)
+// this is used when it was fetched from the cache, right?
+void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data)
{
Q_Q(QNetworkReplyImpl);
if (!q->isOpen())
@@ -452,20 +489,20 @@ void QNetworkReplyImplPrivate::feed(QIODevice *data)
void QNetworkReplyImplPrivate::finished()
{
Q_Q(QNetworkReplyImpl);
- Q_ASSERT_X(state != Finished, "QNetworkReplyImpl",
- "Backend called finished/finishedWithError more than once");
+ if (state == Finished || state == Aborted)
+ return;
state = Finished;
pendingNotifications.clear();
pauseNotificationHandling();
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
- if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull()) {
+ if (totalSize.isNull() || totalSize == -1) {
emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
}
- if (bytesUploaded == -1 && outgoingData) {
+
+ if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer))
emit q->uploadProgress(0, 0);
- }
resumeNotificationHandling();
completeCacheSave();
@@ -521,6 +558,11 @@ void QNetworkReplyImplPrivate::sslErrors(const QList<QSslError> &errors)
#endif
}
+bool QNetworkReplyImplPrivate::isFinished() const
+{
+ return (state == Finished || state == Aborted);
+}
+
QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent)
: QNetworkReply(*new QNetworkReplyImplPrivate, parent)
{
@@ -586,14 +628,14 @@ void QNetworkReplyImpl::close()
*/
qint64 QNetworkReplyImpl::bytesAvailable() const
{
- return QNetworkReply::bytesAvailable() + d_func()->readBuffer.size();
+ return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount();
}
void QNetworkReplyImpl::setReadBufferSize(qint64 size)
{
Q_D(QNetworkReplyImpl);
if (size > d->readBufferMaxSize &&
- size == d->readBuffer.size())
+ size > d->readBuffer.byteAmount())
d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
QNetworkReply::setReadBufferSize(size);
@@ -623,6 +665,12 @@ void QNetworkReplyImpl::ignoreSslErrors()
d->backend->ignoreSslErrors();
}
+void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &errors)
+{
+ Q_D(QNetworkReplyImpl);
+ if (d->backend)
+ d->backend->ignoreSslErrors(errors);
+}
#endif // QT_NO_OPENSSL
/*!
@@ -641,7 +689,7 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen)
return 1;
}
- maxlen = qMin<qint64>(maxlen, d->readBuffer.size());
+ maxlen = qMin<qint64>(maxlen, d->readBuffer.byteAmount());
return d->readBuffer.read(data, maxlen);
}
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 79ffc0d..04f8aa8 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -59,7 +59,9 @@
#include "qnetworkproxy.h"
#include "QtCore/qmap.h"
#include "QtCore/qqueue.h"
+#include "QtCore/qbuffer.h"
#include "private/qringbuffer_p.h"
+#include "private/qbytedata_p.h"
QT_BEGIN_NAMESPACE
@@ -87,14 +89,15 @@ public:
Q_INVOKABLE QSslConfiguration sslConfigurationImplementation() const;
Q_INVOKABLE void setSslConfigurationImplementation(const QSslConfiguration &configuration);
virtual void ignoreSslErrors();
+ Q_INVOKABLE virtual void ignoreSslErrorsImplementation(const QList<QSslError> &errors);
#endif
Q_DECLARE_PRIVATE(QNetworkReplyImpl)
Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceReadyRead())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceReadChannelFinished())
Q_PRIVATE_SLOT(d_func(), void _q_copyReadyRead())
Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
};
class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
@@ -102,15 +105,13 @@ class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
public:
enum InternalNotifications {
NotifyDownstreamReadyWrite,
- NotifyUpstreamReadyRead,
NotifyCloseDownstreamChannel,
- NotifyCloseUpstreamChannel,
NotifyCopyFinished
};
enum State {
Idle,
- Opening,
+ Buffering,
Working,
Finished,
Aborted
@@ -125,6 +126,8 @@ public:
void _q_sourceReadChannelFinished();
void _q_copyReadyRead();
void _q_copyReadChannelFinished();
+ void _q_bufferOutgoingData();
+ void _q_bufferOutgoingDataFinished();
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
@@ -140,17 +143,21 @@ public:
void setCachingEnabled(bool enable);
bool isCachingEnabled() const;
void consume(qint64 count);
+ void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal);
qint64 nextDownstreamBlockSize() const;
- void feed(const QByteArray &data);
- void feed(QIODevice *data);
+ void appendDownstreamData(QByteDataBuffer &data);
+ void appendDownstreamData(QIODevice *data);
void finished();
void error(QNetworkReply::NetworkError code, const QString &errorString);
void metaDataChanged();
void redirectionRequested(const QUrl &target);
void sslErrors(const QList<QSslError> &errors);
+ bool isFinished() const;
+
QNetworkAccessBackend *backend;
QIODevice *outgoingData;
+ QRingBuffer *outgoingDataBuffer;
QIODevice *copyDevice;
QAbstractNetworkCache *networkCache() const;
@@ -166,8 +173,7 @@ public:
QList<QNetworkProxy> proxyList;
#endif
- QRingBuffer readBuffer;
- QRingBuffer writeBuffer;
+ QByteDataBuffer readBuffer;
qint64 bytesDownloaded;
qint64 lastBytesDownloaded;
qint64 bytesUploaded;
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index c5f24e4..3d8874e 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
\brief The QNetworkRequest class holds one request to be sent with the Network Access API.
\since 4.4
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
QNetworkRequest is part of the Network Access API and is the class
@@ -160,6 +160,23 @@ QT_BEGIN_NAMESPACE
Indicates whether the data was obtained from cache
or not.
+ \value DoNotBufferUploadDataAttribute
+ Requests only, type: QVariant::Bool (default: false)
+ Indicates whether the QNetworkAccessManager code is
+ allowed to buffer the upload data, e.g. when doing a HTTP POST.
+ When using this flag with sequential upload data, the ContentLengthHeader
+ header must be set.
+
+ \value HttpPipeliningAllowedAttribute
+ Requests only, type: QVariant::Bool (default: false)
+ Indicates whether the QNetworkAccessManager code is
+ allowed to use HTTP pipelining with this request.
+
+ \value HttpPipeliningWasUsedAttribute
+ Replies only, type: QVariant::Bool
+ Indicates whether the HTTP pipelining was used for receiving
+ this reply.
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
@@ -214,10 +231,9 @@ public:
url = other.url;
#ifndef QT_NO_OPENSSL
+ sslConfiguration = 0;
if (other.sslConfiguration)
sslConfiguration = new QSslConfiguration(*other.sslConfiguration);
- else
- sslConfiguration = 0;
#endif
}
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index 515a375..fab6151 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -75,6 +75,9 @@ public:
CacheLoadControlAttribute,
CacheSaveControlAttribute,
SourceIsFromCacheAttribute,
+ DoNotBufferUploadDataAttribute,
+ HttpPipeliningAllowedAttribute,
+ HttpPipeliningWasUsedAttribute,
User = 1000,
UserMax = 32767
diff --git a/src/network/access/qnetworkrequest_p.h b/src/network/access/qnetworkrequest_p.h
index 22b239f..98fb235 100644
--- a/src/network/access/qnetworkrequest_p.h
+++ b/src/network/access/qnetworkrequest_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 8aa6ff4..6145c43 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -20,10 +20,11 @@ SOURCES += kernel/qauthenticator.cpp \
kernel/qnetworkproxy.cpp \
kernel/qnetworkinterface.cpp
-unix:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
+symbian: SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_symbian.cpp
+unix:!symbian:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp
-mac:LIBS+= -framework SystemConfiguration
+mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation
mac:SOURCES += kernel/qnetworkproxy_mac.cpp
else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
else:SOURCES += kernel/qnetworkproxy_generic.cpp
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index bdb1f88..01bde62 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,6 +46,7 @@
#include <qbytearray.h>
#include <qcryptographichash.h>
#include <qhttp.h>
+#include <qiodevice.h>
#include <qdatastream.h>
#include <qendian.h>
#include <qstring.h>
@@ -63,12 +64,12 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
The QAuthenticator class is usually used in the
- \l{QHttp::}{authenticationRequired()} and
- \l{QHttp::}{proxyAuthenticationRequired()} signals of QHttp and
+ \l{QNetworkAccessManager::}{authenticationRequired()} and
+ \l{QNetworkAccessManager::}{proxyAuthenticationRequired()} signals of QNetworkAccessManager and
QAbstractSocket. The class provides a way to pass back the required
authentication information to the socket when accessing services that
require authentication.
@@ -511,13 +512,13 @@ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge,
credentials += "uri=\"" + path + "\", ";
if (!opaque.isEmpty())
credentials += "opaque=\"" + opaque + "\", ";
- credentials += "response=\"" + response + "\"";
+ credentials += "response=\"" + response + '\"';
if (!options.value("algorithm").isEmpty())
credentials += ", algorithm=" + options.value("algorithm");
if (!options.value("qop").isEmpty()) {
credentials += ", qop=" + qop + ", ";
credentials += "nc=" + nonceCountString + ", ";
- credentials += "cnonce=\"" + cnonce + "\"";
+ credentials += "cnonce=\"" + cnonce + '\"';
}
return credentials;
diff --git a/src/network/kernel/qauthenticator.h b/src/network/kernel/qauthenticator.h
index 6b47a7d..6031f83 100644
--- a/src/network/kernel/qauthenticator.h
+++ b/src/network/kernel/qauthenticator.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qauthenticator_p.h b/src/network/kernel/qauthenticator_p.h
index dc8499c..fbcf8d8 100644
--- a/src/network/kernel/qauthenticator_p.h
+++ b/src/network/kernel/qauthenticator_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 40ec14a..ccfb7ff 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -419,7 +419,7 @@ void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol prot
/*!
\class QHostAddress
\brief The QHostAddress class provides an IP address.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
This class holds an IPv4 or IPv6 address in a platform- and
@@ -523,7 +523,7 @@ QHostAddress::QHostAddress(const struct sockaddr *sockaddr)
Constructs a copy of the given \a address.
*/
QHostAddress::QHostAddress(const QHostAddress &address)
- : d(new QHostAddressPrivate(*address.d))
+ : d(new QHostAddressPrivate(*address.d.data()))
{
}
@@ -559,7 +559,6 @@ QHostAddress::QHostAddress(SpecialAddress address)
*/
QHostAddress::~QHostAddress()
{
- delete d;
}
/*!
@@ -568,7 +567,7 @@ QHostAddress::~QHostAddress()
*/
QHostAddress &QHostAddress::operator=(const QHostAddress &address)
{
- *d = *address.d;
+ *d.data() = *address.d.data();
return *this;
}
@@ -1078,7 +1077,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QHostAddress &address)
{
- d.maybeSpace() << "QHostAddress(" << address.toString() << ")";
+ d.maybeSpace() << "QHostAddress(" << address.toString() << ')';
return d.space();
}
#endif
diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h
index f6f1c85..3f76041 100644
--- a/src/network/kernel/qhostaddress.h
+++ b/src/network/kernel/qhostaddress.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -44,6 +44,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qabstractsocket.h>
struct sockaddr;
@@ -130,7 +131,7 @@ public:
static QPair<QHostAddress, int> parseSubnet(const QString &subnet);
protected:
- QHostAddressPrivate *d;
+ QScopedPointer<QHostAddressPrivate> d;
};
inline bool operator ==(QHostAddress::SpecialAddress address1, const QHostAddress &address2)
diff --git a/src/network/kernel/qhostaddress_p.h b/src/network/kernel/qhostaddress_p.h
index ee4e46a..e309b91 100644
--- a/src/network/kernel/qhostaddress_p.h
+++ b/src/network/kernel/qhostaddress_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index ae105f5..97968e1 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -42,6 +42,7 @@
#include "qhostinfo.h"
#include "qhostinfo_p.h"
+#include "QtCore/qscopedpointer.h"
#include <qabstracteventdispatcher.h>
#include <private/qunicodetables_p.h>
#include <qcoreapplication.h>
@@ -73,7 +74,7 @@ void QHostInfoAgent::staticCleanup()
\reentrant
\inmodule QtNetwork
- \ingroup io
+ \ingroup network
QHostInfo uses the lookup mechanisms provided by the operating
system to find the IP address(es) associated with a host name,
@@ -162,27 +163,24 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
QWindowsSockInit bust; // makes sure WSAStartup was callled
#endif
- // Support for IDNA
- QString lookup = QString::fromLatin1(QUrl::toAce(name));
-
- QHostInfoResult *result = new QHostInfoResult;
- result->autoDelete = false;
- QObject::connect(result, SIGNAL(resultsReady(QHostInfo)),
+ QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
+ result.data()->autoDelete = false;
+ QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
receiver, member);
- int id = result->lookupId = theIdCounter.fetchAndAddRelaxed(1);
+ int id = result.data()->lookupId = theIdCounter.fetchAndAddRelaxed(1);
- if (lookup.isEmpty()) {
+ if (name.isEmpty()) {
QHostInfo info(id);
info.setError(QHostInfo::HostNotFound);
info.setErrorString(QObject::tr("No host name given"));
- QMetaObject::invokeMethod(result, "emitResultsReady", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(result.data(), "emitResultsReady", Qt::QueuedConnection,
Q_ARG(QHostInfo, info));
- result->autoDelete = true;
+ result.take()->autoDelete = true;
return id;
}
QHostInfoAgent *agent = theAgent();
- agent->addHostName(lookup, result);
+ agent->addHostName(name, result.take());
#if !defined QT_NO_THREAD
if (!agent->isRunning())
@@ -226,13 +224,7 @@ QHostInfo QHostInfo::fromName(const QString &name)
qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData());
#endif
- if (!name.isEmpty())
- return QHostInfoAgent::fromName(QLatin1String(QUrl::toAce(name)));
-
- QHostInfo retval;
- retval.d->err = HostNotFound;
- retval.d->errorStr = QObject::tr("No host name given");
- return retval;
+ return QHostInfoAgent::fromName(name);
}
/*!
@@ -327,7 +319,7 @@ QHostInfo::QHostInfo(int id)
Constructs a copy of \a other.
*/
QHostInfo::QHostInfo(const QHostInfo &other)
- : d(new QHostInfoPrivate(*other.d))
+ : d(new QHostInfoPrivate(*other.d.data()))
{
}
@@ -337,7 +329,7 @@ QHostInfo::QHostInfo(const QHostInfo &other)
*/
QHostInfo &QHostInfo::operator=(const QHostInfo &other)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
return *this;
}
@@ -346,7 +338,6 @@ QHostInfo &QHostInfo::operator=(const QHostInfo &other)
*/
QHostInfo::~QHostInfo()
{
- delete d;
}
/*!
diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h
index af346ec..4004679 100644
--- a/src/network/kernel/qhostinfo.h
+++ b/src/network/kernel/qhostinfo.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#define QHOSTINFO_H
#include <QtCore/qlist.h>
+#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qhostaddress.h>
QT_BEGIN_HEADER
@@ -91,7 +92,7 @@ public:
static QString localDomainName();
private:
- QHostInfoPrivate *d;
+ QScopedPointer<QHostInfoPrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index 77bbe0a..ee741aa 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QHostInfo class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
@@ -180,7 +180,8 @@ class QHostInfoPrivate
public:
inline QHostInfoPrivate()
: err(QHostInfo::NoError),
- errorStr(QLatin1String(QT_TRANSLATE_NOOP("QHostInfo", "Unknown error")))
+ errorStr(QLatin1String(QT_TRANSLATE_NOOP("QHostInfo", "Unknown error"))),
+ lookupId(0)
{
}
diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp
index 619483f..2ed61f6 100644
--- a/src/network/kernel/qhostinfo_unix.cpp
+++ b/src/network/kernel/qhostinfo_unix.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -41,8 +41,6 @@
//#define QHOSTINFO_DEBUG
-static const int RESOLVER_TIMEOUT = 2000;
-
#include "qplatformdefs.h"
#include "qhostinfo_p.h"
@@ -52,13 +50,16 @@ static const int RESOLVER_TIMEOUT = 2000;
#include <qurl.h>
#include <qfile.h>
#include <private/qmutexpool_p.h>
+#include <private/qnet_unix_p.h>
-extern "C" {
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
-#include <resolv.h>
-}
+#if defined(Q_OS_VXWORKS)
+# include <hostLib.h>
+#else
+# include <resolv.h>
+#endif
#if defined (QT_NO_GETADDRINFO)
#include <qmutex.h>
@@ -121,7 +122,6 @@ static void resolveLibrary()
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
QHostInfo results;
- results.setHostName(hostName);
#if defined(QHOSTINFO_DEBUG)
qDebug("QHostInfoAgent::fromName(%s) looking up...",
@@ -148,7 +148,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
if (address.setAddress(hostName)) {
// Reverse lookup
// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead.
-#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN)
+#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) && !defined (Q_OS_SYMBIAN)
sockaddr_in sa4;
#ifndef QT_NO_IPV6
sockaddr_in6 sa6;
@@ -180,7 +180,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
}
results.setHostName(QString::fromLatin1(hbuf));
#else
- in_addr_t inetaddr = inet_addr(hostName.toLatin1().constData());
+ in_addr_t inetaddr = qt_safe_inet_addr(hostName.toLatin1().constData());
struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET);
if (!ent) {
results.setError(QHostInfo::HostNotFound);
@@ -191,6 +191,22 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
#endif
}
+ // IDN support
+ QByteArray aceHostname;
+ if (results.hostName().isEmpty()) {
+ // it's a hostname resolution
+ aceHostname = QUrl::toAce(hostName);
+ results.setHostName(hostName);
+ if (aceHostname.isEmpty()) {
+ results.setError(QHostInfo::HostNotFound);
+ results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname"));
+ return results;
+ }
+ } else {
+ // it's an IP reverse resolution
+ aceHostname = results.hostName().toLatin1();
+ }
+
#if !defined (QT_NO_GETADDRINFO)
// Call getaddrinfo, and place all IPv4 addresses at the start and
// the IPv6 addresses at the end of the address list in results.
@@ -202,12 +218,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
hints.ai_flags = Q_ADDRCONFIG;
#endif
- int result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
+ int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
# ifdef Q_ADDRCONFIG
if (result == EAI_BADFLAGS) {
// if the lookup failed with AI_ADDRCONFIG set, try again without it
hints.ai_flags = 0;
- result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
+ result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
}
# endif
@@ -261,7 +277,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
// use one QHostInfoAgent, but if more agents are introduced, locking
// must be provided.
QMutexLocker locker(::getHostByNameMutex());
- hostent *result = gethostbyname(hostName.toLatin1().constData());
+ hostent *result = gethostbyname(aceHostname.constData());
if (result) {
if (result->h_addrtype == AF_INET) {
QList<QHostAddress> addresses;
@@ -276,10 +292,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown address type"));
}
+#if !defined(Q_OS_VXWORKS)
} else if (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA
|| h_errno == NO_ADDRESS) {
results.setError(QHostInfo::HostNotFound);
results.setErrorString(tr("Host not found"));
+#endif
} else {
results.setError(QHostInfo::UnknownError);
results.setErrorString(tr("Unknown error"));
@@ -316,10 +334,12 @@ QString QHostInfo::localHostName()
QString QHostInfo::localDomainName()
{
+#if !defined(Q_OS_VXWORKS)
resolveLibrary();
if (local_res_ninit) {
// using thread-safe version
res_state_ptr state = res_state_ptr(qMalloc(sizeof(*state)));
+ Q_CHECK_PTR(state);
memset(state, 0, sizeof(*state));
local_res_ninit(state);
QString domainName = QUrl::fromAce(state->defdname);
@@ -345,7 +365,7 @@ QString QHostInfo::localDomainName()
domainName = QUrl::fromAce(local_res->dnsrch[0]);
return domainName;
}
-
+#endif
// nothing worked, try doing it by ourselves:
QFile resolvconf;
#if defined(_PATH_RESCONF)
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index 985cbfe..ac9c0ef 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -52,6 +52,7 @@
#include <qlibrary.h>
#include <qtimer.h>
#include <qmutex.h>
+#include <qurl.h>
#include <private/qmutexpool_p.h>
QT_BEGIN_NAMESPACE
@@ -129,7 +130,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
}
QHostInfo results;
- results.setHostName(hostName);
#if defined(QHOSTINFO_DEBUG)
qDebug("QHostInfoAgent::fromName(%p): looking up \"%s\" (IPv6 support is %s)",
@@ -178,12 +178,28 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
}
}
+ // IDN support
+ QByteArray aceHostname;
+ if (results.hostName().isEmpty()) {
+ // it's a hostname resolution
+ aceHostname = QUrl::toAce(hostName);
+ results.setHostName(hostName);
+ if (aceHostname.isEmpty()) {
+ results.setError(QHostInfo::HostNotFound);
+ results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname"));
+ return results;
+ }
+ } else {
+ // it's an IP reverse resolution
+ aceHostname = results.hostName().toLatin1();
+ }
+
if (local_getaddrinfo && local_freeaddrinfo) {
// Call getaddrinfo, and place all IPv4 addresses at the start
// and the IPv6 addresses at the end of the address list in
// results.
qt_addrinfo *res;
- int err = local_getaddrinfo(hostName.toLatin1().constData(), 0, 0, &res);
+ int err = local_getaddrinfo(aceHostname.constData(), 0, 0, &res);
if (err == 0) {
QList<QHostAddress> addresses;
for (qt_addrinfo *p = res; p != 0; p = p->ai_next) {
@@ -218,7 +234,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
}
} else {
// Fall back to gethostbyname, which only supports IPv4.
- hostent *ent = gethostbyname(hostName.toLatin1().constData());
+ hostent *ent = gethostbyname(aceHostname.constData());
if (ent) {
char **p;
QList<QHostAddress> addresses;
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 5b631d5..3a37a98 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -128,7 +128,7 @@ QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data)
for (int i = 0; i < len; ++i) {
if (i)
result += QLatin1Char(':');
-
+
char buf[3];
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
sprintf_s(buf, 3, "%02hX", ushort(data[i]));
@@ -148,7 +148,7 @@ QString QNetworkInterfacePrivate::makeHwAddress(int len, uchar *data)
\since 4.2
\reentrant
- \ingroup io
+ \ingroup network
Each network interface can contain zero or more IP addresses, which
in turn can be associated with a netmask and/or a broadcast
@@ -170,7 +170,7 @@ QNetworkAddressEntry::QNetworkAddressEntry()
object \a other.
*/
QNetworkAddressEntry::QNetworkAddressEntry(const QNetworkAddressEntry &other)
- : d(new QNetworkAddressEntryPrivate(*other.d))
+ : d(new QNetworkAddressEntryPrivate(*other.d.data()))
{
}
@@ -179,7 +179,7 @@ QNetworkAddressEntry::QNetworkAddressEntry(const QNetworkAddressEntry &other)
*/
QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry &other)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
return *this;
}
@@ -188,7 +188,6 @@ QNetworkAddressEntry &QNetworkAddressEntry::operator=(const QNetworkAddressEntry
*/
QNetworkAddressEntry::~QNetworkAddressEntry()
{
- delete d;
}
/*!
@@ -333,7 +332,7 @@ void QNetworkAddressEntry::setBroadcast(const QHostAddress &newBroadcast)
\since 4.2
\reentrant
- \ingroup io
+ \ingroup network
QNetworkInterface represents one network interface attached to the
host where the program is being run. Each network interface may
@@ -594,7 +593,7 @@ static inline QDebug operator<<(QDebug debug, const QNetworkAddressEntry &entry)
debug.nospace() << ", netmask = " << entry.netmask();
if (!entry.broadcast().isNull())
debug.nospace() << ", broadcast = " << entry.broadcast();
- debug.nospace() << ")";
+ debug.nospace() << ')';
return debug.space();
}
@@ -604,8 +603,13 @@ QDebug operator<<(QDebug debug, const QNetworkInterface &networkInterface)
<< ", hardware address = " << networkInterface.hardwareAddress()
<< ", flags = ";
flagsDebug(debug, networkInterface.flags());
+#if defined(Q_CC_RVCT)
+ // RVCT gets confused with << networkInterface.addressEntries(), reason unknown.
+ debug.nospace() << ")\n";
+#else
debug.nospace() << ", entries = " << networkInterface.addressEntries()
<< ")\n";
+#endif
return debug.space();
}
#endif
diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h
index c1e5851..92e79d3 100644
--- a/src/network/kernel/qnetworkinterface.h
+++ b/src/network/kernel/qnetworkinterface.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#define QNETWORKINTERFACE_H
#include <QtCore/qshareddata.h>
+#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qhostaddress.h>
#ifndef QT_NO_NETWORKINTERFACE
@@ -79,7 +80,7 @@ public:
void setBroadcast(const QHostAddress &newBroadcast);
private:
- QNetworkAddressEntryPrivate *d;
+ QScopedPointer<QNetworkAddressEntryPrivate> d;
};
class QNetworkInterfacePrivate;
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index 0b540a2..f6dff41 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qnetworkinterface_symbian.cpp b/src/network/kernel/qnetworkinterface_symbian.cpp
new file mode 100644
index 0000000..74d7e73
--- /dev/null
+++ b/src/network/kernel/qnetworkinterface_symbian.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#define QNETWORKINTERFACE_DEBUG
+
+#include "qnetworkinterface.h"
+#include "qnetworkinterface_p.h"
+#include "../corelib/kernel/qcore_symbian_p.h"
+
+#ifndef QT_NO_NETWORKINTERFACE
+
+#include <in_sock.h>
+#include <in_iface.h>
+#include <es_sock.h>
+
+QT_BEGIN_NAMESPACE
+
+
+static QNetworkInterface::InterfaceFlags convertFlags(const TSoInetInterfaceInfo& aInfo)
+{
+ QNetworkInterface::InterfaceFlags flags = 0;
+ flags |= (aInfo.iState == EIfUp) ? QNetworkInterface::IsUp : QNetworkInterface::InterfaceFlag(0);
+ // We do not have separate flag for running in Symbian OS
+ flags |= (aInfo.iState == EIfUp) ? QNetworkInterface::IsRunning : QNetworkInterface::InterfaceFlag(0);
+ flags |= (aInfo.iFeatures & KIfCanBroadcast) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0);
+ flags |= (aInfo.iFeatures & KIfIsLoopback) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0);
+ flags |= (aInfo.iFeatures & KIfIsPointToPoint) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0);
+ flags |= (aInfo.iFeatures & KIfCanMulticast) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0);
+ return flags;
+}
+
+static QList<QNetworkInterfacePrivate *> interfaceListing()
+{
+ TInt err(KErrNone);
+ QList<QNetworkInterfacePrivate *> interfaces;
+
+ // Connect to Native socket server
+ RSocketServ socketServ;
+ err = socketServ.Connect();
+ if (err)
+ return interfaces;
+
+ // Open dummy socket for interface queries
+ RSocket socket;
+ err = socket.Open(socketServ, _L("udp"));
+ if (err) {
+ socketServ.Close();
+ return interfaces;
+ }
+
+ // Ask socket to start enumerating interfaces
+ err = socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
+ if (err) {
+ socket.Close();
+ socketServ.Close();
+ return interfaces;
+ }
+
+ int ifindex = 0;
+ TPckgBuf<TSoInetInterfaceInfo> infoPckg;
+ TSoInetInterfaceInfo &info = infoPckg();
+ while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, infoPckg) == KErrNone) {
+ // Do not include IPv6 addresses because netmask and broadcast address cannot be determined correctly
+ if (info.iName != KNullDesC && info.iAddress.IsV4Mapped()) {
+ TName address;
+ QNetworkAddressEntry entry;
+ QNetworkInterfacePrivate *iface = 0;
+
+ iface = new QNetworkInterfacePrivate;
+ iface->index = ifindex++;
+ interfaces << iface;
+ iface->name = qt_TDesC2QString(info.iName);
+ iface->flags = convertFlags(info);
+
+ if (/*info.iFeatures&KIfHasHardwareAddr &&*/ info.iHwAddr.Family() != KAFUnspec) {
+ for (TInt i = sizeof(SSockAddr); i < sizeof(SSockAddr) + info.iHwAddr.GetUserLen(); i++) {
+ address.AppendNumFixedWidth(info.iHwAddr[i], EHex, 2);
+ if ((i + 1) < sizeof(SSockAddr) + info.iHwAddr.GetUserLen())
+ address.Append(_L(":"));
+ }
+ address.UpperCase();
+ iface->hardwareAddress = qt_TDesC2QString(address);
+ }
+
+ // Get the address of the interface
+ info.iAddress.Output(address);
+ entry.setIp(QHostAddress(qt_TDesC2QString(address)));
+
+ // Get the interface netmask
+ // For some reason netmask is always 0.0.0.0
+ // info.iNetMask.Output(address);
+ // entry.setNetmask( QHostAddress( qt_TDesC2QString( address ) ) );
+
+ // Workaround: Let Symbian determine netmask based on IP address class
+ // TODO: Works only for IPv4 - Task: 259128 Implement IPv6 support
+ TInetAddr netmask;
+ netmask.NetMask(info.iAddress);
+ netmask.Output(address);
+ entry.setNetmask(QHostAddress(qt_TDesC2QString(address)));
+
+ // Get the interface broadcast address
+ if (iface->flags & QNetworkInterface::CanBroadcast) {
+ // For some reason broadcast address is always 0.0.0.0
+ // info.iBrdAddr.Output(address);
+ // entry.setBroadcast( QHostAddress( qt_TDesC2QString( address ) ) );
+
+ // Workaround: Let Symbian determine broadcast address based on IP address
+ // TODO: Works only for IPv4 - Task: 259128 Implement IPv6 support
+ TInetAddr broadcast;
+ broadcast.NetBroadcast(info.iAddress);
+ broadcast.Output(address);
+ entry.setBroadcast(QHostAddress(qt_TDesC2QString(address)));
+ }
+
+ // Add new entry to interface address entries
+ iface->addressEntries << entry;
+
+#if defined(QNETWORKINTERFACE_DEBUG)
+ printf("\n Found network interface %s, interface flags:\n\
+ IsUp = %d, IsRunning = %d, CanBroadcast = %d,\n\
+ IsLoopBack = %d, IsPointToPoint = %d, CanMulticast = %d, \n\
+ ip = %s, netmask = %s, broadcast = %s,\n\
+ hwaddress = %s",
+ iface->name.toLatin1().constData(),
+ iface->flags & QNetworkInterface::IsUp, iface->flags & QNetworkInterface::IsRunning, iface->flags & QNetworkInterface::CanBroadcast,
+ iface->flags & QNetworkInterface::IsLoopBack, iface->flags & QNetworkInterface::IsPointToPoint, iface->flags & QNetworkInterface::CanMulticast,
+ entry.ip().toString().toLatin1().constData(), entry.netmask().toString().toLatin1().constData(), entry.broadcast().toString().toLatin1().constData(),
+ iface->hardwareAddress.toLatin1().constData());
+#endif
+ }
+ }
+
+ // we will try to use routing info to detect more precisely
+ // netmask and then ::postProcess() should calculate
+ // broadcast addresses
+
+ // use dummy socket to start enumerating routes
+ err = socket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl);
+ if (err) {
+ socket.Close();
+ socketServ.Close();
+ // return what we have
+ // up to this moment
+ return interfaces;
+ }
+
+ TSoInetRouteInfo routeInfo;
+ TPckg<TSoInetRouteInfo> routeInfoPkg(routeInfo);
+ while (socket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, routeInfoPkg) == KErrNone) {
+ TName address;
+
+ // get interface address
+ routeInfo.iIfAddr.Output(address);
+ QHostAddress ifAddr(qt_TDesC2QString(address));
+ if (ifAddr.isNull())
+ continue;
+
+ routeInfo.iDstAddr.Output(address);
+ QHostAddress destination(qt_TDesC2QString(address));
+ if (destination.isNull() || destination != ifAddr)
+ continue;
+
+ // search interfaces
+ for (int ifindex = 0; ifindex < interfaces.size(); ++ifindex) {
+ QNetworkInterfacePrivate *iface = interfaces.at(ifindex);
+ for (int eindex = 0; eindex < iface->addressEntries.size(); ++eindex) {
+ QNetworkAddressEntry entry = iface->addressEntries.at(eindex);
+ if (entry.ip() != ifAddr) {
+ continue;
+ } else if (entry.ip().protocol() != QAbstractSocket::IPv4Protocol) {
+ // skip if not IPv4 address (e.g. IPv6)
+ // as results not reliable on Symbian
+ continue;
+ } else {
+ routeInfo.iNetMask.Output(address);
+ QHostAddress netmask(qt_TDesC2QString(address));
+ entry.setNetmask(netmask);
+ // NULL boradcast address for
+ // ::postProcess to have effect
+ entry.setBroadcast(QHostAddress());
+ iface->addressEntries.replace(eindex, entry);
+ }
+ }
+ }
+ }
+
+ socket.Close();
+ socketServ.Close();
+
+ return interfaces;
+}
+
+QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
+{
+ return interfaceListing();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKINTERFACE
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index a06083b..d1080d2 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#include "qnetworkinterface.h"
#include "qnetworkinterface_p.h"
#include "qalgorithms.h"
+#include "private/qnet_unix_p.h"
#ifndef QT_NO_NETWORKINTERFACE
@@ -123,7 +124,7 @@ static QSet<QByteArray> interfaceNames(int socket)
interfaceList.ifc_len = storageBuffer.size();
// get the interface list
- if (::ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {
if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) {
// if the buffer was big enough, break
storageBuffer.resize(interfaceList.ifc_len);
@@ -198,7 +199,7 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfa
#ifdef SIOCGIFNAME
// Get the canonical name
QByteArray oldName = req.ifr_name;
- if (::ioctl(socket, SIOCGIFNAME, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) {
iface->name = QString::fromLatin1(req.ifr_name);
// reset the name:
@@ -211,13 +212,13 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfa
}
// Get interface flags
- if (::ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {
iface->flags = convertFlags(req.ifr_flags);
}
#ifdef SIOCGIFHWADDR
// Get the HW address
- if (::ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {
uchar *addr = (uchar *)&req.ifr_addr;
iface->hardwareAddress = iface->makeHwAddress(6, addr);
}
@@ -232,7 +233,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
QList<QNetworkInterfacePrivate *> interfaces;
int socket;
- if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
+ if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
return interfaces; // error
QSet<QByteArray> names = interfaceNames(socket);
@@ -247,7 +248,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
// Get the interface broadcast address
QNetworkAddressEntry entry;
if (iface->flags & QNetworkInterface::CanBroadcast) {
- if (::ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {
sockaddr *sa = &req.ifr_addr;
if (sa->sa_family == AF_INET)
entry.setBroadcast(addressFromSockaddr(sa));
@@ -255,13 +256,13 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
}
// Get the interface netmask
- if (::ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFNETMASK, &req) >= 0) {
sockaddr *sa = &req.ifr_addr;
entry.setNetmask(addressFromSockaddr(sa));
}
// Get the address of the interface
- if (::ioctl(socket, SIOCGIFADDR, &req) >= 0) {
+ if (qt_safe_ioctl(socket, SIOCGIFADDR, &req) >= 0) {
sockaddr *sa = &req.ifr_addr;
entry.setIp(addressFromSockaddr(sa));
}
@@ -392,7 +393,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
QList<QNetworkInterfacePrivate *> interfaces;
int socket;
- if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
+ if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
return interfaces; // error
ifaddrs *interfaceListing;
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 0645969..23c413f 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -66,19 +66,14 @@ static void resolveLibs()
if (!done) {
done = true;
- HINSTANCE iphlpapiHnd;
- QT_WA({
- iphlpapiHnd = LoadLibraryW(L"iphlpapi");
- }, {
- iphlpapiHnd = LoadLibraryA("iphlpapi");
- });
+ HINSTANCE iphlpapiHnd = LoadLibrary(L"iphlpapi");
if (iphlpapiHnd == NULL)
- return; // failed to load, probably Windows 95
+ return;
#if defined(Q_OS_WINCE)
- ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddressW(iphlpapiHnd, L"GetAdaptersInfo");
- ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddressW(iphlpapiHnd, L"GetAdaptersAddresses");
- ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddressW(iphlpapiHnd, L"GetNetworkParams");
+ ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo");
+ ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses");
+ ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams");
#else
ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo");
ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses");
@@ -115,6 +110,8 @@ static QHash<QHostAddress, QHostAddress> ipv4Netmasks()
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_INFO *)qMalloc(bufSize);
+ if (!pAdapter)
+ return ipv4netmasks;
// try again
if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
qFree(pAdapter);
@@ -156,7 +153,8 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_ADDRESSES *)qMalloc(bufSize);
-
+ if (!pAdapter)
+ return interfaces;
// try again
if (ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) {
qFree(pAdapter);
@@ -236,7 +234,8 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWin2k()
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_INFO *)qMalloc(bufSize);
-
+ if (!pAdapter)
+ return interfaces;
// try again
if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) {
qFree(pAdapter);
@@ -306,7 +305,8 @@ QString QHostInfo::localDomainName()
pinfo = &info;
if (ptrGetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
pinfo = (FIXED_INFO *)qMalloc(bufSize);
-
+ if (!pinfo)
+ return QString();
// try again
if (ptrGetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) {
qFree(pinfo);
diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h
index feebd0a..85291df 100644
--- a/src/network/kernel/qnetworkinterface_win_p.h
+++ b/src/network/kernel/qnetworkinterface_win_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -54,7 +54,7 @@
//
#include <winsock2.h>
-#include <windows.h>
+#include <qt_windows.h>
#include <time.h>
QT_BEGIN_NAMESPACE
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index fb74fda..908f01f 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -48,16 +48,16 @@
\brief The QNetworkProxy class provides a network layer proxy.
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
QNetworkProxy provides the method for configuring network layer
proxy support to the Qt network classes. The currently supported
classes are QAbstractSocket, QTcpSocket, QUdpSocket, QTcpServer,
- QHttp and QFtp. The proxy support is designed to be as transparent
- as possible. This means that existing network-enabled applications
- that you have written should automatically support network proxy
- using the following code.
+ QNetworkAccessManager and QFtp. The proxy support is designed to
+ be as transparent as possible. This means that existing
+ network-enabled applications that you have written should
+ automatically support network proxy using the following code.
\snippet doc/src/snippets/code/src_network_kernel_qnetworkproxy.cpp 0
@@ -160,8 +160,7 @@
\row
\o Caching-only HTTP
\o Implemented using normal HTTP commands, it is useful only
- in the context of HTTP requests (see QHttp,
- QNetworkAccessManager)
+ in the context of HTTP requests (see QNetworkAccessManager)
\o CachingCapability, HostNameLookupCapability
\row
@@ -221,6 +220,7 @@
#ifndef QT_NO_NETWORKPROXY
+#include "private/qnetworkproxy_p.h"
#include "private/qsocks5socketengine_p.h"
#include "private/qhttpsocketengine_p.h"
#include "qauthenticator.h"
@@ -324,7 +324,7 @@ QList<QNetworkProxy> QGlobalNetworkProxy::proxyForQuery(const QNetworkProxyQuery
return result;
}
-Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy);
+Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy)
namespace {
template<bool> struct StaticAssertTest;
@@ -1119,7 +1119,7 @@ void QNetworkProxyQuery::setUrl(const QUrl &url)
\brief The QNetworkProxyFactory class provides fine-grained proxy selection.
\since 4.5
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
QNetworkProxyFactory is an extension to QNetworkProxy, allowing
@@ -1157,6 +1157,29 @@ QNetworkProxyFactory::~QNetworkProxyFactory()
{
}
+
+/*!
+ Enables the use of the platform-specific proxy settings, and only those.
+ See systemProxyForQuery() for more information.
+
+ Internally, this method (when called with \a enable set to true)
+ sets an application-wide proxy factory. For this reason, this method
+ is mutually exclusive with setApplicationProxyFactory: calling
+ setApplicationProxyFactory overrides the use of the system-wide proxy,
+ and calling setUseSystemConfigurationEnabled overrides any
+ application proxy or proxy factory that was previously set.
+
+ \since 4.6
+*/
+void QNetworkProxyFactory::setUseSystemConfigurationEnabled(bool enable)
+{
+ if (enable) {
+ setApplicationProxyFactory(new QSystemConfigurationProxyFactory);
+ } else {
+ setApplicationProxyFactory(0);
+ }
+}
+
/*!
Sets the application-wide proxy factory to be \a factory. This
function will take ownership of that object and will delete it
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index c64f408..01a88b8 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -171,6 +171,7 @@ public:
virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()) = 0;
+ static void setUseSystemConfigurationEnabled(bool enable);
static void setApplicationProxyFactory(QNetworkProxyFactory *factory);
static QList<QNetworkProxy> proxyForQuery(const QNetworkProxyQuery &query);
static QList<QNetworkProxy> systemProxyForQuery(const QNetworkProxyQuery &query = QNetworkProxyQuery());
diff --git a/src/network/kernel/qnetworkproxy_generic.cpp b/src/network/kernel/qnetworkproxy_generic.cpp
index 673c262..8fad0c8 100644
--- a/src/network/kernel/qnetworkproxy_generic.cpp
+++ b/src/network/kernel/qnetworkproxy_generic.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index 9e2b0e4..3ef977a 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/kernel/qnetworkproxy_p.h b/src/network/kernel/qnetworkproxy_p.h
new file mode 100644
index 0000000..facbfed
--- /dev/null
+++ b/src/network/kernel/qnetworkproxy_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 David Faure <dfaure@kdab.net>
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKPROXY_P_H
+#define QNETWORKPROXY_P_H
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_NETWORKPROXY
+
+QT_BEGIN_NAMESPACE
+
+class QSystemConfigurationProxyFactory : public QNetworkProxyFactory
+{
+public:
+ QSystemConfigurationProxyFactory() : QNetworkProxyFactory() {}
+
+ virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery& query)
+ {
+ QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(query);
+
+ // Make sure NoProxy is in the list, so that QTcpServer can work:
+ // it searches for the first proxy that can has the ListeningCapability capability
+ // if none have (as is the case with HTTP proxies), it fails to bind.
+ // NoProxy allows it to fallback to the 'no proxy' case and bind.
+ proxies.append(QNetworkProxy::NoProxy);
+
+ return proxies;
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKINTERFACE
+
+#endif
+
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index f0fff2f..8080261 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,15 +43,13 @@
#ifndef QT_NO_NETWORKPROXY
-#if defined(UNICODE)
-
#include <qmutex.h>
#include <qstringlist.h>
#include <qregexp.h>
#include <qurl.h>
#include <string.h>
-#include <windows.h>
+#include <qt_windows.h>
#include <wininet.h>
/*
@@ -269,15 +267,13 @@ void QWindowsSystemProxy::init()
if (initialized)
return;
initialized = true;
- if (QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based)
- return; // no point, this library is only available on 2k, XP and up
#ifdef Q_OS_WINCE
// Windows CE does not have any of the following API
return;
#else
// load the winhttp.dll library
- HINSTANCE winhttpHnd = LoadLibraryW(L"winhttp");
+ HINSTANCE winhttpHnd = LoadLibrary(L"winhttp");
if (!winhttpHnd)
return; // failed to load
@@ -367,8 +363,13 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
if (sp->isAutoConfig) {
WINHTTP_PROXY_INFO proxyInfo;
- // try to get the proxy config for the URL, if we have a URL
+ // try to get the proxy config for the URL
QUrl url = query.url();
+ // url could be empty, e.g. from QNetworkProxy::applicationProxy(), that's fine,
+ // we'll still ask for the proxy.
+ // But for a file url, we know we don't need one.
+ if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc"))
+ return sp->defaultResult;
if (query.queryType() != QNetworkProxyQuery::UrlRequest) {
// change the scheme to https, maybe it'll work
url.setScheme(QLatin1String("https"));
@@ -401,15 +402,6 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
return parseServerList(query, sp->proxyServerList);
}
-#else // !UNICODE
-
-QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &)
-{
- return QList<QNetworkProxy>() << QNetworkProxy::NoProxy;
-}
-
-#endif
-
QT_END_NAMESPACE
#endif
diff --git a/src/network/kernel/qurlinfo.cpp b/src/network/kernel/qurlinfo.cpp
index bd3d25d..46950e9 100644
--- a/src/network/kernel/qurlinfo.cpp
+++ b/src/network/kernel/qurlinfo.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -85,7 +85,7 @@ public:
\brief The QUrlInfo class stores information about URLs.
\ingroup io
- \ingroup misc
+ \ingroup network
The information about a URL that can be retrieved includes name(),
permissions(), owner(), group(), size(), lastModified(),
diff --git a/src/network/kernel/qurlinfo.h b/src/network/kernel/qurlinfo.h
index 52ddbe4..273e1e0 100644
--- a/src/network/kernel/qurlinfo.h
+++ b/src/network/kernel/qurlinfo.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/network.pro b/src/network/network.pro
index d476b56..e890b94 100644
--- a/src/network/network.pro
+++ b/src/network/network.pro
@@ -3,6 +3,13 @@
TARGET = QtNetwork
QPRO_PWD = $$PWD
DEFINES += QT_BUILD_NETWORK_LIB QT_NO_USING_NAMESPACE
+#DEFINES += QLOCALSERVER_DEBUG QLOCALSOCKET_DEBUG
+#DEFINES += QNETWORKDISKCACHE_DEBUG
+#DEFINES += QSSLSOCKET_DEBUG
+#DEFINES += QHOSTINFO_DEBUG
+#DEFINES += QABSTRACTSOCKET_DEBUG QNATIVESOCKETENGINE_DEBUG
+#DEFINES += QTCPSOCKETENGINE_DEBUG QTCPSOCKET_DEBUG QTCPSERVER_DEBUG QSSLSOCKET_DEBUG
+#DEFINES += QUDPSOCKET_DEBUG QUDPSERVER_DEBUG
QT = core
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x64000000
@@ -15,3 +22,9 @@ include(socket/socket.pri)
include(ssl/ssl.pri)
QMAKE_LIBS += $$QMAKE_LIBS_NETWORK
+
+
+symbian {
+ TARGET.UID3=0x2001B2DE
+ LIBS += -lesock -linsock
+}
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index d0bc150..98740ba 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -48,7 +48,7 @@
common to all socket types.
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
QAbstractSocket is the base class for QTcpSocket and QUdpSocket
@@ -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"
@@ -437,6 +453,9 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
peerPort(0),
socketEngine(0),
cachedSocketDescriptor(-1),
+#ifdef Q_OS_LINUX
+ addToBytesAvailable(0),
+#endif
readBufferMaxSize(0),
readBuffer(QABSTRACTSOCKET_BUFFERSIZE),
writeBuffer(QABSTRACTSOCKET_BUFFERSIZE),
@@ -445,6 +464,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
connectTimer(0),
connectTimeElapsed(0),
hostLookupId(-1),
+ socketType(QAbstractSocket::UnknownSocketType),
state(QAbstractSocket::UnconnectedState),
socketError(QAbstractSocket::UnknownSocketError)
{
@@ -852,7 +872,7 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo)
if (i != 0) s += ", ";
s += addresses.at(i).toString();
}
- s += "}";
+ s += '}';
qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());
#endif
@@ -1053,6 +1073,7 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt()
#endif
if (socketEngine)
socketEngine->setWriteNotificationEnabled(false);
+
connectTimer->stop();
if (addresses.isEmpty()) {
@@ -1265,8 +1286,9 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint
(int) openMode);
#endif
- if (d->state == ConnectedState || d->state == ConnectingState || d->state == ClosingState) {
- qWarning("QAbstractSocket::connectToHost() called when already connecting/connected to \"%s\"", qPrintable(hostName));
+ if (d->state == ConnectedState || d->state == ConnectingState
+ || d->state == ClosingState || d->state == HostLookupState) {
+ qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName));
return;
}
@@ -1548,6 +1570,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.
@@ -1658,13 +1730,13 @@ bool QAbstractSocket::waitForConnected(int msecs)
}
/*!
- This function blocks until data is available for reading and the
+ This function blocks until new data is available for reading and the
\l{QIODevice::}{readyRead()} signal has been emitted. The function
will timeout after \a msecs milliseconds; the default timeout is
30000 milliseconds.
The function returns true if the readyRead() signal is emitted and
- there is data available for reading; otherwise it returns false
+ there is new data available for reading; otherwise it returns false
(if an error occurred or the operation timed out).
\sa waitForBytesWritten()
@@ -2596,7 +2668,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, QAbstractSocket::SocketError er
debug << "QAbstractSocket::ProxyProtocolError";
break;
default:
- debug << "QAbstractSocket::SocketError(" << int(error) << ")";
+ debug << "QAbstractSocket::SocketError(" << int(error) << ')';
break;
}
return debug;
@@ -2627,7 +2699,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, QAbstractSocket::SocketState st
debug << "QAbstractSocket::ClosingState";
break;
default:
- debug << "QAbstractSocket::SocketState(" << int(state) << ")";
+ debug << "QAbstractSocket::SocketState(" << int(state) << ')';
break;
}
return debug;
diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h
index 75a873f..6cc86ef 100644
--- a/src/network/socket/qabstractsocket.h
+++ b/src/network/socket/qabstractsocket.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -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/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h
index ea03152..49605c5 100644
--- a/src/network/socket/qabstractsocket_p.h
+++ b/src/network/socket/qabstractsocket_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QAbstractSocket class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/network/socket/qabstractsocketengine.cpp b/src/network/socket/qabstractsocketengine.cpp
index fb3d070..f9e6030 100644
--- a/src/network/socket/qabstractsocketengine.cpp
+++ b/src/network/socket/qabstractsocketengine.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index 032915a..0d7f84f 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -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 fba04b3..9ef92e1 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -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;
}
@@ -735,6 +752,7 @@ QHttpSocketEnginePrivate::QHttpSocketEnginePrivate()
, readNotificationPending(false)
, writeNotificationPending(false)
, connectionNotificationPending(false)
+ , pendingResponseData(0)
{
socket = 0;
state = QHttpSocketEngine::None;
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index a423116..a20df8a 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp
index 83af719..20291d1 100644
--- a/src/network/socket/qlocalserver.cpp
+++ b/src/network/socket/qlocalserver.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -78,8 +78,6 @@ QT_BEGIN_NAMESPACE
to use it without one. In that case, you must use waitForNewConnection(),
which blocks until either a connection is available or a timeout expires.
- Note that this feature is not supported on Windows 9x.
-
\sa QLocalSocket, QTcpServer
*/
@@ -276,9 +274,17 @@ QLocalSocket *QLocalServer::nextPendingConnection()
if (d->pendingConnections.isEmpty())
return 0;
QLocalSocket *nextSocket = d->pendingConnections.dequeue();
+#ifdef Q_OS_SYMBIAN
+ if(!d->socketNotifier)
+ return nextSocket;
+#endif
+#ifndef QT_LOCALSOCKET_TCP
+ if (d->pendingConnections.size() <= d->maxPendingConnections)
#ifndef Q_OS_WIN
- d->socketNotifier->setEnabled(d->pendingConnections.size()
- <= d->maxPendingConnections);
+ d->socketNotifier->setEnabled(true);
+#else
+ d->connectionEventNotifier->setEnabled(true);
+#endif
#endif
return nextSocket;
}
diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h
index 455301b..acc3eb5 100644
--- a/src/network/socket/qlocalserver.h
+++ b/src/network/socket/qlocalserver.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -86,15 +86,7 @@ protected:
private:
Q_DISABLE_COPY(QLocalServer)
-#if defined(QT_LOCALSOCKET_TCP)
Q_PRIVATE_SLOT(d_func(), void _q_onNewConnection())
-#elif defined(Q_OS_WIN)
- Q_PRIVATE_SLOT(d_func(), void _q_openSocket(HANDLE handle))
- Q_PRIVATE_SLOT(d_func(), void _q_stoppedListening())
- Q_PRIVATE_SLOT(d_func(), void _q_setError(QAbstractSocket::SocketError error, const QString &errorString))
-#else
- Q_PRIVATE_SLOT(d_func(), void _q_socketActivated())
-#endif
};
#endif // QT_NO_LOCALSERVER
diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h
index 711810c..09f40c2 100644
--- a/src/network/socket/qlocalserver_p.h
+++ b/src/network/socket/qlocalserver_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -63,7 +63,7 @@
# include <qtcpserver.h>
#elif defined(Q_OS_WIN)
# include <qt_windows.h>
-# include <qthread.h>
+# include <private/qwineventnotifier_p.h>
#else
# include <private/qnativesocketengine_p.h>
# include <qsocketnotifier.h>
@@ -71,52 +71,13 @@
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-
-/*!
- \internal
- QLocalServerThread exists because Windows does not have a
- way to provide notifications when there is a new connections to
- the server.
- */
-class QLocalServerThread : public QThread
-{
- Q_OBJECT
-
-Q_SIGNALS:
- void connected(HANDLE newSocket);
- void error(QAbstractSocket::SocketError error, const QString &errorString);
-
-public:
- QLocalServerThread(QObject *parent = 0);
- ~QLocalServerThread();
- void closeServer();
-
-public:
- QString setName(const QString &name);
- void run();
- void stop();
- bool makeHandle();
-
- HANDLE gotConnectionEvent;
- QQueue<HANDLE> pendingHandles;
- int maxPendingConnections;
-private:
- HANDLE stopEvent;
- QString fullServerName;
-};
-
-#endif
-
class QLocalServerPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QLocalServer)
public:
QLocalServerPrivate() :
-#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
- inWaitingFunction(false),
-#elif !defined(QT_LOCALSOCKET_TCP)
+#if !defined(QT_LOCALSOCKET_TCP) && !defined(Q_OS_WIN)
listenSocket(-1), socketNotifier(0),
#endif
maxPendingConnections(30), error(QAbstractSocket::UnknownSocketError)
@@ -128,22 +89,26 @@ public:
static bool removeServer(const QString &name);
void closeServer();
void waitForNewConnection(int msec, bool *timedOut);
+ void _q_onNewConnection();
#if defined(QT_LOCALSOCKET_TCP)
- void _q_onNewConnection();
QTcpServer tcpServer;
QMap<quintptr, QTcpSocket*> socketMap;
#elif defined(Q_OS_WIN)
- void _q_openSocket(HANDLE socket);
- void _q_stoppedListening();
- void _q_setError(QAbstractSocket::SocketError error, const QString &errorString);
+ struct Listener {
+ HANDLE handle;
+ OVERLAPPED overlapped;
+ };
+
+ void setError(const QString &function);
+ bool addListener();
- QLocalServerThread waitForConnection;
- bool inWaitingFunction;
+ QList<Listener> listeners;
+ HANDLE eventHandle;
+ QWinEventNotifier *connectionEventNotifier;
#else
void setError(const QString &function);
- void _q_socketActivated();
int listenSocket;
QSocketNotifier *socketNotifier;
diff --git a/src/network/socket/qlocalserver_tcp.cpp b/src/network/socket/qlocalserver_tcp.cpp
index 77d9889..f34696f 100644
--- a/src/network/socket/qlocalserver_tcp.cpp
+++ b/src/network/socket/qlocalserver_tcp.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index a981ebe..01452ea 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#include "qlocalserver_p.h"
#include "qlocalsocket.h"
#include "qlocalsocket_p.h"
+#include "qnet_unix_p.h"
#ifndef QT_NO_LOCALSERVER
@@ -53,6 +54,10 @@
#include <qdir.h>
#include <qdatetime.h>
+#ifdef Q_OS_VXWORKS
+# include <selectLib.h>
+#endif
+
QT_BEGIN_NAMESPACE
void QLocalServerPrivate::init()
@@ -88,7 +93,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
serverName = requestedServerName;
// create the unix socket
- listenSocket = qSocket(PF_UNIX, SOCK_STREAM, 0);
+ listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0);
if (-1 == listenSocket) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
@@ -106,8 +111,26 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
fullServerName.toLatin1().size() + 1);
+#ifdef Q_OS_SYMBIAN
+ // In SYMBIAN OS it can currently happen that accept is called twice,
+ // once from waitForNewConnection and once via QSocketNotfier activity
+ //
+ // As an workaround, we set the socket to non blocking so possible
+ // subsequent call to accept will not block in any case
+ //
+ // This change can be removed once more generic fix to select thread
+ // syncronization problem is implemented.
+ int flags = fcntl(listenSocket, F_GETFL, 0);
+ if (-1 == flags
+ || -1 == (fcntl(listenSocket, F_SETFL, flags | O_NONBLOCK))) {
+ setError(QLatin1String("QLocalServer::listen"));
+ closeServer();
+ return false;
+ }
+#endif
+
// bind
- if(-1 == qBind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
+ if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
setError(QLatin1String("QLocalServer::listen"));
// if address is in use already, just close the socket, but do not delete the file
if(errno == EADDRINUSE)
@@ -120,7 +143,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
}
// listen for connections
- if (-1 == qListen(listenSocket, 50)) {
+ if (-1 == qt_safe_listen(listenSocket, 50)) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
listenSocket = -1;
@@ -132,7 +155,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
socketNotifier = new QSocketNotifier(listenSocket,
QSocketNotifier::Read, q);
q->connect(socketNotifier, SIGNAL(activated(int)),
- q, SLOT(_q_socketActivated()));
+ q, SLOT(_q_onNewConnection()));
socketNotifier->setEnabled(maxPendingConnections > 0);
return true;
}
@@ -164,7 +187,7 @@ void QLocalServerPrivate::closeServer()
We have received a notification that we can read on the listen socket.
Accept the new socket.
*/
-void QLocalServerPrivate::_q_socketActivated()
+void QLocalServerPrivate::_q_onNewConnection()
{
Q_Q(QLocalServer);
if (-1 == listenSocket)
@@ -172,7 +195,7 @@ void QLocalServerPrivate::_q_socketActivated()
::sockaddr_un addr;
QT_SOCKLEN_T length = sizeof(sockaddr_un);
- int connectedSocket = qAccept(listenSocket, (sockaddr *)&addr, &length);
+ int connectedSocket = qt_safe_accept(listenSocket, (sockaddr *)&addr, &length);
if(-1 == connectedSocket) {
setError(QLatin1String("QLocalSocket::activated"));
closeServer();
@@ -209,7 +232,7 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
break;
}
if (result > 0)
- _q_socketActivated();
+ _q_onNewConnection();
}
if (timedOut)
*timedOut = (result == 0);
diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp
index 15d856b..93cbe92 100644
--- a/src/network/socket/qlocalserver_win.cpp
+++ b/src/network/socket/qlocalserver_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -44,81 +44,26 @@
#include "qlocalsocket.h"
#include <qdebug.h>
-#include <qdatetime.h>
-#include <qcoreapplication.h>
-#include <QMetaType>
// The buffer size need to be 0 otherwise data could be
// lost if the socket that has written data closes the connection
// before it is read. Pipewriter is used for write buffering.
#define BUFSIZE 0
-QT_BEGIN_NAMESPACE
+// ###: This should be a property. Should replace the insane 50 on unix as well.
+#define SYSTEM_MAX_PENDING_SOCKETS 8
-QLocalServerThread::QLocalServerThread(QObject *parent) : QThread(parent),
- maxPendingConnections(1)
-{
- stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- gotConnectionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-}
-
-QLocalServerThread::~QLocalServerThread()
-{
- stop();
- closeServer();
- CloseHandle(stopEvent);
- CloseHandle(gotConnectionEvent);
-}
-
-void QLocalServerThread::stop()
-{
- if (isRunning()) {
- SetEvent(stopEvent);
- wait();
- ResetEvent(stopEvent);
- }
-}
-
-void QLocalServerThread::closeServer()
-{
- while (!pendingHandles.isEmpty())
- CloseHandle(pendingHandles.dequeue());
-}
-
-QString QLocalServerThread::setName(const QString &name)
-{
- QString pipePath = QLatin1String("\\\\.\\pipe\\");
- if (name.startsWith(pipePath))
- fullServerName = name;
- else
- fullServerName = pipePath + name;
- for (int i = pendingHandles.count(); i < maxPendingConnections; ++i)
- if (!makeHandle())
- break;
- return fullServerName;
-}
+QT_BEGIN_NAMESPACE
-bool QLocalServerThread::makeHandle()
+bool QLocalServerPrivate::addListener()
{
- if (pendingHandles.count() >= maxPendingConnections)
- return false;
+ // The object must not change its address once the
+ // contained OVERLAPPED struct is passed to Windows.
+ listeners << Listener();
+ Listener &listener = listeners.last();
- HANDLE handle = INVALID_HANDLE_VALUE;
- QT_WA({
- handle = CreateNamedPipeW(
- (TCHAR*)fullServerName.utf16(), // pipe name
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
- PIPE_TYPE_MESSAGE | // message type pipe
- PIPE_READMODE_MESSAGE | // message-read mode
- PIPE_WAIT, // blocking mode
- PIPE_UNLIMITED_INSTANCES, // max. instances
- BUFSIZE, // output buffer size
- BUFSIZE, // input buffer size
- 3000, // client time-out
- NULL);
- }, {
- handle = CreateNamedPipeA(
- fullServerName.toLocal8Bit().constData(), // pipe name
+ listener.handle = CreateNamedPipe(
+ (const wchar_t *)fullServerName.utf16(), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
@@ -128,69 +73,44 @@ bool QLocalServerThread::makeHandle()
BUFSIZE, // input buffer size
3000, // client time-out
NULL);
- });
- if (INVALID_HANDLE_VALUE == handle) {
+ if (listener.handle == INVALID_HANDLE_VALUE) {
+ setError(QLatin1String("QLocalServerPrivate::addListener"));
+ listeners.removeLast();
return false;
}
- pendingHandles.enqueue(handle);
+
+ memset(&listener.overlapped, 0, sizeof(listener.overlapped));
+ listener.overlapped.hEvent = eventHandle;
+ if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) {
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ break;
+ case ERROR_PIPE_CONNECTED:
+ SetEvent(eventHandle);
+ break;
+ default:
+ CloseHandle(listener.handle);
+ setError(QLatin1String("QLocalServerPrivate::addListener"));
+ listeners.removeLast();
+ return false;
+ }
+ } else {
+ Q_ASSERT_X(false, "QLocalServerPrivate::addListener", "The impossible happened");
+ SetEvent(eventHandle);
+ }
return true;
}
-void QLocalServerThread::run()
+void QLocalServerPrivate::setError(const QString &function)
{
- OVERLAPPED op;
- HANDLE handleArray[2];
- memset(&op, 0, sizeof(op));
- handleArray[0] = op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- handleArray[1] = stopEvent;
- HANDLE handle = INVALID_HANDLE_VALUE;
-
- forever {
- if (INVALID_HANDLE_VALUE == handle) {
- makeHandle();
- if (!pendingHandles.isEmpty())
- handle = pendingHandles.dequeue();
- }
- if (INVALID_HANDLE_VALUE == handle) {
- int windowsError = GetLastError();
- QString function = QLatin1String("QLocalServer::run");
- QString errorString = QLocalServer::tr("%1: Unknown error %2").arg(function).arg(windowsError);
- emit error(QAbstractSocket::UnknownSocketError, errorString);
- CloseHandle(handleArray[0]);
- SetEvent(gotConnectionEvent);
- return;
- }
-
- BOOL isConnected = ConnectNamedPipe(handle, &op) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
- if (!isConnected) {
- switch (WaitForMultipleObjects(2, handleArray, FALSE, INFINITE))
- {
- case WAIT_OBJECT_0 + 1:
- CloseHandle(handle);
- CloseHandle(handleArray[0]);
- return;
- }
- }
- emit connected(handle);
- handle = INVALID_HANDLE_VALUE;
- ResetEvent(handleArray[0]);
- SetEvent(gotConnectionEvent);
- }
+ int windowsError = GetLastError();
+ errorString = QString::fromLatin1("%1: %2").arg(function).arg(qt_error_string(windowsError));
+ error = QAbstractSocket::UnknownSocketError;
}
void QLocalServerPrivate::init()
{
- Q_Q(QLocalServer);
- qRegisterMetaType<HANDLE>("HANDLE");
- q->connect(&waitForConnection, SIGNAL(connected(HANDLE)),
- q, SLOT(_q_openSocket(HANDLE)), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(finished()),
- q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(terminated()),
- q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(error(QAbstractSocket::SocketError, const QString &)),
- q, SLOT(_q_setError(QAbstractSocket::SocketError, const QString &)));
}
bool QLocalServerPrivate::removeServer(const QString &name)
@@ -201,35 +121,71 @@ bool QLocalServerPrivate::removeServer(const QString &name)
bool QLocalServerPrivate::listen(const QString &name)
{
- fullServerName = waitForConnection.setName(name);
- serverName = name;
- waitForConnection.start();
- return true;
-}
+ Q_Q(QLocalServer);
-void QLocalServerPrivate::_q_setError(QAbstractSocket::SocketError e, const QString &eString)
-{
- error = e;
- errorString = eString;
-}
+ QString pipePath = QLatin1String("\\\\.\\pipe\\");
+ if (name.startsWith(pipePath))
+ fullServerName = name;
+ else
+ fullServerName = pipePath + name;
-void QLocalServerPrivate::_q_stoppedListening()
-{
- Q_Q(QLocalServer);
- if (!inWaitingFunction)
- q->close();
+ // Use only one event for all listeners of one socket.
+ // The idea is that listener events are rare, so polling all listeners once in a while is
+ // cheap compared to waiting for N additional events in each iteration of the main loop.
+ eventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
+ connectionEventNotifier = new QWinEventNotifier(eventHandle , q);
+ q->connect(connectionEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onNewConnection()));
+
+ for (int i = 0; i < SYSTEM_MAX_PENDING_SOCKETS; ++i)
+ if (!addListener())
+ return false;
+ return true;
}
-void QLocalServerPrivate::_q_openSocket(HANDLE handle)
+void QLocalServerPrivate::_q_onNewConnection()
{
Q_Q(QLocalServer);
- q->incomingConnection((int)handle);
+ DWORD dummy;
+
+ // Reset first, otherwise we could reset an event which was asserted
+ // immediately after we checked the conn status.
+ ResetEvent(eventHandle);
+
+ // Testing shows that there is indeed absolutely no guarantee which listener gets
+ // a client connection first, so there is no way around polling all of them.
+ for (int i = 0; i < listeners.size(); ) {
+ HANDLE handle = listeners[i].handle;
+ if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) {
+ listeners.removeAt(i);
+
+ addListener();
+
+ if (pendingConnections.size() > maxPendingConnections)
+ connectionEventNotifier->setEnabled(false);
+
+ // Make this the last thing so connected slots can wreak the least havoc
+ q->incomingConnection((quintptr)handle);
+ } else {
+ if (GetLastError() != ERROR_IO_INCOMPLETE) {
+ setError(QLatin1String("QLocalServerPrivate::_q_onNewConnection"));
+ closeServer();
+ return;
+ }
+
+ ++i;
+ }
+ }
}
void QLocalServerPrivate::closeServer()
{
- waitForConnection.stop();
- waitForConnection.closeServer();
+ connectionEventNotifier->setEnabled(false); // Otherwise, closed handle is checked before deleter runs
+ connectionEventNotifier->deleteLater();
+ connectionEventNotifier = 0;
+ CloseHandle(eventHandle);
+ for (int i = 0; i < listeners.size(); ++i)
+ CloseHandle(listeners[i].handle);
+ listeners.clear();
}
void QLocalServerPrivate::waitForNewConnection(int msecs, bool *timedOut)
@@ -238,14 +194,12 @@ void QLocalServerPrivate::waitForNewConnection(int msecs, bool *timedOut)
if (!pendingConnections.isEmpty() || !q->isListening())
return;
- DWORD result = WaitForSingleObject(waitForConnection.gotConnectionEvent,
- (msecs == -1) ? INFINITE : msecs);
+ DWORD result = WaitForSingleObject(eventHandle, (msecs == -1) ? INFINITE : msecs);
if (result == WAIT_TIMEOUT) {
if (timedOut)
*timedOut = true;
} else {
- ResetEvent(waitForConnection.gotConnectionEvent);
- QCoreApplication::instance()->processEvents();
+ _q_onNewConnection();
}
}
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index b2c1c71..54b2be3 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE
waitForReadyRead(), waitForBytesWritten(), and waitForDisconnected()
which blocks until the operation is complete or the timeout expires.
- Note that this feature is not supported on Window 9x.
+ Note that this feature is not supported on versions of Windows earlier than
+ Windows XP.
\sa QLocalServer
*/
@@ -102,7 +103,7 @@ QT_BEGIN_NAMESPACE
opened in the mode specified by \a openMode, and enters the socket state
specified by \a socketState.
- Note: It is not possible to initialize two local sockets with the same
+ \note It is not possible to initialize two local sockets with the same
native socket descriptor.
\sa socketDescriptor(), state(), openMode()
@@ -207,10 +208,10 @@ QT_BEGIN_NAMESPACE
Returns true if the socket is valid and ready for use; otherwise
returns false.
- Note: The socket's state must be ConnectedState before reading
+ \note The socket's state must be ConnectedState before reading
and writing can occur.
- \sa state()
+ \sa state(), connectToServer()
*/
/*!
@@ -243,9 +244,9 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool QLocalSocket::waitForConnected(int msec)
+ \fn bool QLocalSocket::waitForConnected(int msecs)
- Waits until the socket is connected, up to \a msec milliseconds. If the
+ Waits until the socket is connected, up to \a msecs milliseconds. If the
connection has been established, this function returns true; otherwise
it returns false. In the case where it returns false, you can call
error() to determine the cause of the error.
@@ -255,7 +256,7 @@ QT_BEGIN_NAMESPACE
\snippet doc/src/snippets/code/src_network_socket_qlocalsocket_unix.cpp 0
- If msecs is -1, this function will not time out.
+ If \a msecs is -1, this function will not time out.
\sa connectToServer(), connected()
*/
@@ -274,7 +275,7 @@ QT_BEGIN_NAMESPACE
\snippet doc/src/snippets/code/src_network_socket_qlocalsocket_unix.cpp 1
- If msecs is -1, this function will not time out.
+ If \a msecs is -1, this function will not time out.
\sa disconnectFromServer(), close()
*/
@@ -309,9 +310,10 @@ QT_BEGIN_NAMESPACE
parameter describes the type of error that occurred.
QLocalSocket::LocalSocketError is not a registered metatype, so for queued
- connections, you will have to register it with Q_DECLARE_METATYPE.
+ connections, you will have to register it with Q_DECLARE_METATYPE() and
+ qRegisterMetaType().
- \sa error(), errorString()
+ \sa error(), errorString(), {Creating Custom Qt Types}
*/
/*!
@@ -321,9 +323,10 @@ QT_BEGIN_NAMESPACE
The \a socketState parameter is the new state.
QLocalSocket::SocketState is not a registered metatype, so for queued
- connections, you will have to register it with Q_DECLARE_METATYPE.
+ connections, you will have to register it with Q_DECLARE_METATYPE() and
+ qRegisterMetaType().
- \sa state()
+ \sa state(), {Creating Custom Qt Types}
*/
/*!
@@ -365,7 +368,7 @@ QString QLocalSocket::serverName() const
/*!
Returns the server path that the socket is connected to.
- Note: This is platform specific
+ \note The return value of this function is platform specific.
\sa connectToServer(), serverName()
*/
@@ -468,7 +471,7 @@ QDebug operator<<(QDebug debug, QLocalSocket::LocalSocketError error)
debug << "QLocalSocket::UnknownSocketError";
break;
default:
- debug << "QLocalSocket::SocketError(" << int(error) << ")";
+ debug << "QLocalSocket::SocketError(" << int(error) << ')';
break;
}
return debug;
@@ -490,7 +493,7 @@ QDebug operator<<(QDebug debug, QLocalSocket::LocalSocketState state)
debug << "QLocalSocket::ClosingState";
break;
default:
- debug << "QLocalSocket::SocketState(" << int(state) << ")";
+ debug << "QLocalSocket::SocketState(" << int(state) << ')';
break;
}
return debug;
diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h
index cc43553..7c0fe78 100644
--- a/src/network/socket/qlocalsocket.h
+++ b/src/network/socket/qlocalsocket.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -134,6 +134,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_notified())
Q_PRIVATE_SLOT(d_func(), void _q_canWrite())
Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed())
+ Q_PRIVATE_SLOT(d_func(), void _q_emitReadyRead())
#else
Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState))
Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError))
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index 69575f6..a7248f6 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -65,6 +65,7 @@
#elif defined(Q_OS_WIN)
# include "private/qwindowspipewriter_p.h"
# include "private/qringbuffer_p.h"
+# include <private/qwineventnotifier_p.h>
#else
# include "private/qnativesocketengine_p.h"
# include <qtcpsocket.h>
@@ -74,43 +75,6 @@
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-static inline int qSocket(int af, int socketype, int proto)
-{
- int ret;
- while((ret = qt_socket_socket(af, socketype, proto)) == -1 && errno == EINTR){}
- return ret;
-}
-
-static inline int qBind(int fd, const sockaddr *sa, int len)
-{
- int ret;
- while((ret = QT_SOCKET_BIND(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
- return ret;
-}
-
-static inline int qConnect(int fd, const sockaddr *sa, int len)
-{
- int ret;
- while((ret = QT_SOCKET_CONNECT(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){}
- return ret;
-}
-
-static inline int qListen(int fd, int backlog)
-{
- int ret;
- while((ret = qt_socket_listen(fd, backlog)) == -1 && errno == EINTR){}
- return ret;
-}
-
-static inline int qAccept(int fd, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
-{
- int ret;
- while((ret = qt_socket_accept(fd, addr, addrlen)) == -1 && errno == EINTR){}
- return ret;
-}
-#endif //#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-
#if !defined(Q_OS_WIN) || defined(QT_LOCALSOCKET_TCP)
class QLocalUnixSocket : public QTcpSocket
{
@@ -172,18 +136,23 @@ public:
void _q_notified();
void _q_canWrite();
void _q_pipeClosed();
- qint64 readData(char *data, qint64 maxSize);
- qint64 bytesAvailable();
- bool readFromSocket();
+ void _q_emitReadyRead();
+ DWORD bytesAvailable();
+ void startAsyncRead();
+ bool completeAsyncRead();
+ void checkReadyRead();
HANDLE handle;
OVERLAPPED overlapped;
QWindowsPipeWriter *pipeWriter;
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
- QTimer dataNotifier;
+ int actualReadBufferSize;
+ QWinEventNotifier *dataReadNotifier;
QLocalSocket::LocalSocketError error;
- bool readyReadEmitted;
+ bool readSequenceStarted;
+ bool pendingReadyRead;
bool pipeClosed;
+ static const qint64 initialReadBufferSize = 4096;
#else
QLocalUnixSocket unixSocket;
QString generateErrorString(QLocalSocket::LocalSocketError, const QString &function) const;
diff --git a/src/network/socket/qlocalsocket_tcp.cpp b/src/network/socket/qlocalsocket_tcp.cpp
index 7ceaf03e..f096441 100644
--- a/src/network/socket/qlocalsocket_tcp.cpp
+++ b/src/network/socket/qlocalsocket_tcp.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
index 22efee8..d3d172b 100644
--- a/src/network/socket/qlocalsocket_unix.cpp
+++ b/src/network/socket/qlocalsocket_unix.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -41,6 +41,7 @@
#include "qlocalsocket.h"
#include "qlocalsocket_p.h"
+#include "qnet_unix_p.h"
#ifndef QT_NO_LOCALSOCKET
@@ -55,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
@@ -232,12 +237,12 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
}
// create the socket
- if (-1 == (d->connectingSocket = qSocket(PF_UNIX, SOCK_STREAM, 0))) {
+ if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) {
d->errorOccurred(UnsupportedSocketOperationError,
QLatin1String("QLocalSocket::connectToServer"));
return;
}
-
+#ifndef Q_OS_SYMBIAN
// set non blocking so we can try to connect and it wont wait
int flags = fcntl(d->connectingSocket, F_GETFL, 0);
if (-1 == flags
@@ -246,6 +251,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
QLatin1String("QLocalSocket::connectToServer"));
return;
}
+#endif
// _q_connectToSocket does the actual connecting
d->connectingName = name;
@@ -282,7 +288,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
}
::memcpy(name.sun_path, connectingPathName.toLatin1().data(),
connectingPathName.toLatin1().size() + 1);
- if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
+ if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
QString function = QLatin1String("QLocalSocket::connectToServer");
switch (errno)
{
@@ -303,7 +309,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
case EAGAIN:
// Try again later, all of the sockets listening are full
if (!delayConnect) {
- delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write);
+ delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write, q);
q->connect(delayConnect, SIGNAL(activated(int)), q, SLOT(_q_connectToSocket()));
}
if (!connectTimer) {
@@ -514,9 +520,9 @@ bool QLocalSocket::waitForConnected(int msec)
if (state() != ConnectingState)
return (state() == ConnectedState);
- fd_set readfds;
- FD_ZERO(&readfds);
- FD_SET(d->connectingSocket, &readfds);
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(d->connectingSocket, &fds);
timeval timeout;
timeout.tv_sec = msec / 1000;
@@ -532,7 +538,14 @@ bool QLocalSocket::waitForConnected(int msec)
timer.start();
while (state() == ConnectingState
&& (-1 == msec || timer.elapsed() < msec)) {
- result = ::select(d->connectingSocket + 1, &readfds, 0, 0, &timeout);
+#ifdef Q_OS_SYMBIAN
+ // On Symbian, ready-to-write is signaled when non-blocking socket
+ // connect is finised. Is ready-to-read really used on other
+ // UNIX paltforms when using non-blocking AF_UNIX socket?
+ result = ::select(d->connectingSocket + 1, 0, &fds, 0, &timeout);
+#else
+ result = ::select(d->connectingSocket + 1, &fds, 0, 0, &timeout);
+#endif
if (-1 == result && errno != EINTR) {
d->errorOccurred( QLocalSocket::UnknownSocketError,
QLatin1String("QLocalSocket::waitForConnected"));
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 2541047..e15ac65 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -48,13 +48,13 @@
QT_BEGIN_NAMESPACE
-#define NOTIFYTIMEOUT 100
-
void QLocalSocketPrivate::init()
{
Q_Q(QLocalSocket);
- QObject::connect(&dataNotifier, SIGNAL(timeout()), q, SLOT(_q_notified()));
+ memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ dataReadNotifier = new QWinEventNotifier(overlapped.hEvent, q);
+ q->connect(dataReadNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_notified()));
}
void QLocalSocketPrivate::setErrorString(const QString &function)
@@ -101,8 +101,10 @@ QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
handle(INVALID_HANDLE_VALUE),
pipeWriter(0),
readBufferMaxSize(0),
+ actualReadBufferSize(0),
error(QLocalSocket::UnknownSocketError),
- readyReadEmitted(false),
+ readSequenceStarted(false),
+ pendingReadyRead(false),
pipeClosed(false),
state(QLocalSocket::UnconnectedState)
{
@@ -137,25 +139,14 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
forever {
DWORD permissions = (openMode & QIODevice::ReadOnly) ? GENERIC_READ : 0;
permissions |= (openMode & QIODevice::WriteOnly) ? GENERIC_WRITE : 0;
- QT_WA({
- localSocket = CreateFileW(
- (TCHAR*)d->fullServerName.utf16(), // pipe name
- permissions,
- 0, // no sharing
- NULL, // default security attributes
- OPEN_EXISTING, // opens existing pipe
- FILE_FLAG_OVERLAPPED,
- NULL); // no template file
- }, {
- localSocket = CreateFileA(
- d->fullServerName.toLocal8Bit().constData(), // pipe name
- permissions,
- 0, // no sharing
- NULL, // default security attributes
- OPEN_EXISTING, // opens existing pipe
- FILE_FLAG_OVERLAPPED,
- NULL); // no template file
- });
+ localSocket = CreateFile((const wchar_t *)d->fullServerName.utf16(), // pipe name
+ permissions,
+ 0, // no sharing
+ NULL, // default security attributes
+ OPEN_EXISTING, // opens existing pipe
+ FILE_FLAG_OVERLAPPED,
+ NULL); // no template file
+
if (localSocket != INVALID_HANDLE_VALUE)
break;
DWORD error = GetLastError();
@@ -165,13 +156,8 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
}
// All pipe instances are busy, so wait until connected or up to 5 seconds.
- QT_WA({
- if (!WaitNamedPipeW((TCHAR*)d->fullServerName.utf16(), 5000))
- break;
- }, {
- if (!WaitNamedPipeA(d->fullServerName.toLocal8Bit().constData(), 5000))
- break;
- });
+ if (!WaitNamedPipe((const wchar_t *)d->fullServerName.utf16(), 5000))
+ break;
}
if (localSocket == INVALID_HANDLE_VALUE) {
@@ -182,7 +168,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
// we have a valid handle
d->serverName = name;
- if (setSocketDescriptor((quintptr)localSocket), openMode) {
+ if (setSocketDescriptor((quintptr)localSocket, ConnectedState, openMode)) {
d->handle = localSocket;
emit connected();
}
@@ -192,81 +178,122 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
qint64 QLocalSocket::readData(char *data, qint64 maxSize)
{
Q_D(QLocalSocket);
- if (d->readBuffer.isEmpty()) {
- if (!d->readFromSocket()) {
- if (d->pipeClosed)
- return -1;
- return 0;
- }
- }
- if (!d->dataNotifier.isActive() && d->threadData->eventDispatcher)
- d->dataNotifier.start(NOTIFYTIMEOUT);
-
- if (d->readBuffer.isEmpty())
- return qint64(0);
-
- // If readFromSocket() read data, copy it to its destination.
- if (maxSize == 1) {
+ qint64 readSoFar;
+ // If startAsyncRead() read data, copy it to its destination.
+ if (maxSize == 1 && d->actualReadBufferSize > 0) {
*data = d->readBuffer.getChar();
- return 1;
+ d->actualReadBufferSize--;
+ readSoFar = 1;
+ } else {
+ qint64 bytesToRead = qMin(qint64(d->actualReadBufferSize), maxSize);
+ readSoFar = 0;
+ while (readSoFar < bytesToRead) {
+ const char *ptr = d->readBuffer.readPointer();
+ int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
+ qint64(d->readBuffer.nextDataBlockSize()));
+ memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ readSoFar += bytesToReadFromThisBlock;
+ d->readBuffer.free(bytesToReadFromThisBlock);
+ d->actualReadBufferSize -= bytesToReadFromThisBlock;
+ }
}
- qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize);
- qint64 readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = d->readBuffer.readPointer();
- int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
- d->readBuffer.nextDataBlockSize());
- memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- d->readBuffer.free(bytesToReadFromThisBlock);
+ if (d->pipeClosed) {
+ QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
+ } else {
+ if (!d->readSequenceStarted)
+ d->startAsyncRead();
+ d->checkReadyRead();
}
+
return readSoFar;
}
/*!
\internal
- read from the socket
+ Schedules or cancels a readyRead() emission depending on actual data availability
*/
-qint64 QLocalSocketPrivate::readData(char *data, qint64 maxSize)
+void QLocalSocketPrivate::checkReadyRead()
{
- DWORD bytesRead = 0;
- overlapped.Offset = 0;
- overlapped.OffsetHigh = 0;
- bool success = ReadFile(handle, data, maxSize, &bytesRead, &overlapped);
- if (!success && GetLastError() == ERROR_IO_PENDING)
- if (GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE))
- success = true;
- if (!success) {
- setErrorString(QLatin1String("QLocalSocket::readData"));
- return 0;
+ if (actualReadBufferSize > 0) {
+ if (!pendingReadyRead) {
+ Q_Q(QLocalSocket);
+ QTimer::singleShot(0, q, SLOT(_q_emitReadyRead()));
+ pendingReadyRead = true;
+ }
+ } else {
+ pendingReadyRead = false;
}
- return bytesRead;
}
/*!
\internal
Reads data from the socket into the readbuffer
*/
-bool QLocalSocketPrivate::readFromSocket()
+void QLocalSocketPrivate::startAsyncRead()
{
- qint64 bytesToRead = bytesAvailable();
- if (bytesToRead == 0)
- return false;
+ do {
+ DWORD bytesToRead = bytesAvailable();
+ if (bytesToRead == 0) {
+ // There are no bytes in the pipe but we need to
+ // start the overlapped read with some buffer size.
+ bytesToRead = initialReadBufferSize;
+ }
- if (readBufferMaxSize && bytesToRead
- > (readBufferMaxSize - readBuffer.size()))
- bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
+ bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (bytesToRead == 0) {
+ // Buffer is full. User must read data from the buffer
+ // before we can read more from the pipe.
+ return;
+ }
+ }
- char *ptr = readBuffer.reserve(bytesToRead);
- qint64 readBytes = readData(ptr, bytesToRead);
- if (readBytes == 0) {
- readBuffer.chop(bytesToRead);
+ char *ptr = readBuffer.reserve(bytesToRead);
+
+ readSequenceStarted = true;
+ if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
+ completeAsyncRead();
+ } else {
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ // This is not an error. We're getting notified, when data arrives.
+ return;
+ case ERROR_PIPE_NOT_CONNECTED:
+ {
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeClosed = true;
+ return;
+ }
+ default:
+ setErrorString(QLatin1String("QLocalSocketPrivate::startAsyncRead"));
+ return;
+ }
+ }
+ } while (!readSequenceStarted);
+}
+
+/*!
+ \internal
+ Sets the correct size of the read buffer after a read operation.
+ Returns false, if an error occured or the connection dropped.
+ */
+bool QLocalSocketPrivate::completeAsyncRead()
+{
+ ResetEvent(overlapped.hEvent);
+ readSequenceStarted = false;
+
+ DWORD bytesRead;
+ if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
+ if (GetLastError() != ERROR_PIPE_NOT_CONNECTED)
+ setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
return false;
}
- readyReadEmitted = false;
- readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)));
+
+ actualReadBufferSize += bytesRead;
+ readBuffer.truncate(actualReadBufferSize);
return true;
}
@@ -275,8 +302,9 @@ qint64 QLocalSocket::writeData(const char *data, qint64 maxSize)
Q_D(QLocalSocket);
if (!d->pipeWriter) {
d->pipeWriter = new QWindowsPipeWriter(d->handle, this);
- d->pipeWriter->start();
connect(d->pipeWriter, SIGNAL(canWrite()), this, SLOT(_q_canWrite()));
+ connect(d->pipeWriter, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64)));
+ d->pipeWriter->start();
}
return d->pipeWriter->write(data, maxSize);
}
@@ -289,11 +317,9 @@ void QLocalSocket::abort()
/*!
The number of bytes available from the pipe
*/
-qint64 QLocalSocketPrivate::bytesAvailable()
+DWORD QLocalSocketPrivate::bytesAvailable()
{
Q_Q(QLocalSocket);
- if (q->state() != QLocalSocket::ConnectedState)
- return 0;
DWORD bytes;
if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
return bytes;
@@ -316,7 +342,7 @@ qint64 QLocalSocket::bytesAvailable() const
{
Q_D(const QLocalSocket);
qint64 available = QIODevice::bytesAvailable();
- available += (qint64) d->readBuffer.size();
+ available += (qint64) d->actualReadBufferSize;
return available;
}
@@ -343,7 +369,6 @@ void QLocalSocket::close()
QIODevice::close();
d->state = ClosingState;
emit stateChanged(d->state);
- d->readyReadEmitted = false;
emit readChannelFinished();
d->serverName = QString();
d->fullServerName = QString();
@@ -352,10 +377,13 @@ void QLocalSocket::close()
disconnectFromServer();
return;
}
+ d->readSequenceStarted = false;
+ d->pendingReadyRead = false;
d->pipeClosed = false;
DisconnectNamedPipe(d->handle);
CloseHandle(d->handle);
d->handle = INVALID_HANDLE_VALUE;
+ ResetEvent(d->overlapped.hEvent);
d->state = UnconnectedState;
emit stateChanged(d->state);
emit disconnected();
@@ -363,7 +391,6 @@ void QLocalSocket::close()
delete d->pipeWriter;
d->pipeWriter = 0;
}
- d->dataNotifier.stop();
}
bool QLocalSocket::flush()
@@ -397,12 +424,15 @@ bool QLocalSocket::setSocketDescriptor(quintptr socketDescriptor,
{
Q_D(QLocalSocket);
d->readBuffer.clear();
+ d->actualReadBufferSize = 0;
QIODevice::open(openMode);
d->handle = (int*)socketDescriptor;
d->state = socketState;
emit stateChanged(d->state);
- if (d->threadData->eventDispatcher)
- d->dataNotifier.start(NOTIFYTIMEOUT);
+ if (d->state == ConnectedState && openMode.testFlag(QIODevice::ReadOnly)) {
+ d->startAsyncRead();
+ d->checkReadyRead();
+ }
return true;
}
@@ -416,20 +446,21 @@ void QLocalSocketPrivate::_q_canWrite()
void QLocalSocketPrivate::_q_notified()
{
Q_Q(QLocalSocket);
- if (0 != bytesAvailable()) {
- if (readBufferMaxSize == 0 || readBuffer.size() < readBufferMaxSize) {
- if (!readFromSocket()) {
- return;
- }
- // wait until buffer is cleared before starting again
- if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize) {
- dataNotifier.stop();
- }
- }
- if (!readyReadEmitted) {
- readyReadEmitted = true;
- q->emit readyRead();
- }
+ if (!completeAsyncRead()) {
+ pipeClosed = true;
+ return;
+ }
+ startAsyncRead();
+ pendingReadyRead = false;
+ emit q->readyRead();
+}
+
+void QLocalSocketPrivate::_q_emitReadyRead()
+{
+ if (pendingReadyRead) {
+ Q_Q(QLocalSocket);
+ pendingReadyRead = false;
+ emit q->readyRead();
}
}
@@ -462,11 +493,15 @@ bool QLocalSocket::waitForDisconnected(int msecs)
Q_D(QLocalSocket);
if (state() == UnconnectedState)
return false;
+ if (!openMode().testFlag(QIODevice::ReadOnly)) {
+ qWarning("QLocalSocket::waitForDisconnected isn't supported for write only pipes.");
+ return false;
+ }
QIncrementalSleepTimer timer(msecs);
forever {
- d->_q_notified();
- if (d->pipeClosed)
- close();
+ d->bytesAvailable(); // to check if PeekNamedPipe fails
+ if (d->pipeClosed)
+ close();
if (state() == UnconnectedState)
return true;
Sleep(timer.nextSleepTime());
@@ -486,22 +521,24 @@ bool QLocalSocket::isValid() const
bool QLocalSocket::waitForReadyRead(int msecs)
{
Q_D(QLocalSocket);
- QIncrementalSleepTimer timer(msecs);
- forever {
- d->_q_notified();
- if (bytesAvailable() > 0) {
- if (!d->readyReadEmitted) {
- d->readyReadEmitted = true;
- emit readyRead();
- }
- return true;
- }
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
+ if (bytesAvailable() > 0)
+ return true;
+
+ if (d->state != QLocalSocket::ConnectedState)
+ return false;
+
+ Q_ASSERT(d->readSequenceStarted);
+ DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
+ switch (result) {
+ case WAIT_OBJECT_0:
+ d->_q_notified();
+ return true;
+ case WAIT_TIMEOUT:
+ return false;
}
+ qWarning("QLocalSocket::waitForReadyRead WaitForSingleObject failed with error code %d.", int(GetLastError()));
return false;
}
@@ -511,27 +548,11 @@ bool QLocalSocket::waitForBytesWritten(int msecs)
if (!d->pipeWriter)
return false;
- QIncrementalSleepTimer timer(msecs);
- forever {
- if (d->pipeWriter->hadWritten())
- return true;
-
- if (d->pipeWriter->bytesToWrite() == 0)
- return false;
-
- // Wait for the pipe writer to acknowledge that it has
- // written. This will succeed if either the pipe writer has
- // already written the data, or if it manages to write data
- // within the given timeout.
- if (d->pipeWriter->waitForWrite(0))
- return true;
-
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
- }
-
- return false;
+ // Wait for the pipe writer to acknowledge that it has
+ // written. This will succeed if either the pipe writer has
+ // already written the data, or if it manages to write data
+ // within the given timeout.
+ return d->pipeWriter->waitForWrite(msecs);
}
QT_END_NAMESPACE
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 5657b29..3d9aa61 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -47,7 +47,7 @@
\brief The QNativeSocketEngine class provides low level access to a socket.
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
QtSocketLayer provides basic socket functionality provided by the
@@ -381,16 +381,27 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb
return false;
}
+
// Make sure we receive out-of-band data
+ // On Symbian OS this works only with native IP stack, not with WinSock
if (socketType == QAbstractSocket::TcpSocket
&& !setOption(ReceiveOutOfBandData, 1)) {
qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data");
}
- // Set the send and receive buffer sizes to a magic size, found
- // most optimal for our platforms.
- setReceiveBufferSize(49152);
- setSendBufferSize(49152);
+ // Before Qt 4.6, we always set the send and receive buffer size to 49152 as
+ // this was found to be an optimal value. However, modern OS
+ // all have some kind of auto tuning for this and we therefore don't set
+ // this explictly anymore.
+ // If it introduces any performance regressions for Qt 4.6.x (x > 0) then
+ // it will be put back in.
+ //
+ // You can use tests/manual/qhttpnetworkconnection to test HTTP download speed
+ // with this.
+ //
+ // pre-4.6:
+ // setReceiveBufferSize(49152);
+ // setSendBufferSize(49152);
d->socketType = socketType;
d->socketProtocol = protocol;
@@ -911,7 +922,7 @@ bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWri
d_func()->fetchConnectionParameters();
return true;
}
-#endif
+#endif
if (ret == 0) {
if (timedOut)
*timedOut = true;
@@ -1086,7 +1097,10 @@ protected:
bool QExceptionNotifier::event(QEvent *e)
{
if (e->type() == QEvent::SockAct) {
- engine->exceptionNotification();
+ if (engine->state() == QAbstractSocket::ConnectingState)
+ engine->connectionNotification();
+ else
+ engine->exceptionNotification();
return true;
}
return QSocketNotifier::event(e);
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index 95a5221..084775f 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -52,45 +52,20 @@
//
// We mean it.
//
-
#include "QtNetwork/qhostaddress.h"
#include "private/qabstractsocketengine_p.h"
#ifndef Q_OS_WIN
-# include "qplatformdefs.h"
+# include "qplatformdefs.h"
#else
-# include <winsock2.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#ifndef Q_OS_WIN
-// Almost always the same. If not, specify in qplatformdefs.h.
-#if !defined(QT_SOCKOPTLEN_T)
-# define QT_SOCKOPTLEN_T QT_SOCKLEN_T
+# include <winsock2.h>
#endif
-// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
-static inline int qt_socket_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen)
-{ return ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen)); }
-#if defined(accept)
-# undef accept
+#ifdef Q_OS_SYMBIAN
+#include <private/qeventdispatcher_symbian_p.h>
+#include <unistd.h>
#endif
-// UnixWare 7 redefines listen -> _listen
-static inline int qt_socket_listen(int s, int backlog)
-{ return ::listen(s, backlog); }
-#if defined(listen)
-# undef listen
-#endif
-
-// UnixWare 7 redefines socket -> _socket
-static inline int qt_socket_socket(int domain, int type, int protocol)
-{ return ::socket(domain, type, protocol); }
-#if defined(socket)
-# undef socket
-#endif
-
-#endif
+QT_BEGIN_NAMESPACE
// Use our own defines and structs which we know are correct
# define QT_SS_MAXSIZE 128
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 40f9eec..3df3ab7 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -40,8 +40,8 @@
****************************************************************************/
//#define QNATIVESOCKETENGINE_DEBUG
-
#include "qnativesocketengine_p.h"
+#include "private/qnet_unix_p.h"
#include "qiodevice.h"
#include "qhostaddress.h"
#include "qvarlengtharray.h"
@@ -64,6 +64,13 @@
#include <ctype.h>
#endif
+#ifdef Q_OS_SYMBIAN // ### TODO: Are these headers right?
+#include <sys/socket.h>
+#include <netinet/in.h>
+#else
+#include <netinet/tcp.h>
+#endif
+
QT_BEGIN_NAMESPACE
#if defined QNATIVESOCKETENGINE_DEBUG
@@ -100,6 +107,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
static void qt_ignore_sigpipe()
{
+#ifndef Q_NO_POSIX_SIGNALS
// Set to ignore SIGPIPE once only.
static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER(0);
if (atom.testAndSetRelaxed(0, 1)) {
@@ -108,6 +116,10 @@ static void qt_ignore_sigpipe()
noaction.sa_handler = SIG_IGN;
::sigaction(SIGPIPE, &noaction, 0);
}
+#else
+ // Posix signals are not supported by the underlying platform
+ // so we don't need to ignore sigpipe signal explicitly
+#endif
}
/*
@@ -126,7 +138,7 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po
*addr = tmpAddress;
#ifndef QT_NO_IPV6IFNAME
char scopeid[IFNAMSIZ];
- if (::if_indextoname(s->a6.sin6_scope_id, scopeid) > 0) {
+ if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
addr->setScopeId(QLatin1String(scopeid));
} else
#endif
@@ -161,7 +173,11 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
int protocol = AF_INET;
#endif
int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
- int socket = qt_socket_socket(protocol, type, 0);
+#ifdef Q_OS_SYMBIAN
+ int socket = ::socket(protocol, type, 0);
+#else
+ int socket = qt_safe_socket(protocol, type, 0);
+#endif
if (socket <= 0) {
switch (errno) {
@@ -188,6 +204,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
// Ensure that the socket is closed on exec*().
::fcntl(socket, F_SETFD, FD_CLOEXEC);
+
socketDescriptor = socket;
return true;
}
@@ -202,6 +219,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;
@@ -221,12 +240,20 @@ 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;
}
@@ -241,6 +268,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;
@@ -253,6 +282,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
@@ -266,7 +296,19 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
#endif
return false;
}
-
+#else // Q_OS_VXWORKS
+ int onoff = 1;
+#ifdef Q_OS_SYMBIAN
+ if (::ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
+#else
+ if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
+#endif
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
+#endif
+ return false;
+ }
+#endif // Q_OS_VXWORKS
return true;
}
case QNativeSocketEngine::AddressReusable:
@@ -281,13 +323,24 @@ 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)
{
+#ifdef QNATIVESOCKETENGINE_DEBUG
+ qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
+#endif
+
struct sockaddr_in sockAddrIPv4;
struct sockaddr *sockAddrPtr = 0;
QT_SOCKLEN_T sockAddrSize = 0;
@@ -325,8 +378,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
} else {
// unreachable
}
-
- int connectResult = QT_SOCKET_CONNECT(socketDescriptor, sockAddrPtr, sockAddrSize);
+#ifdef Q_OS_SYMBIAN
+ int connectResult = ::connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+#else
+ int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
+#endif
if (connectResult == -1) {
switch (errno) {
case EISCONN:
@@ -430,6 +486,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
}
int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
+
if (bindResult < 0) {
switch(errno) {
case EADDRINUSE:
@@ -466,7 +523,11 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
bool QNativeSocketEnginePrivate::nativeListen(int backlog)
{
- if (qt_socket_listen(socketDescriptor, backlog) < 0) {
+#ifdef Q_OS_SYMBIAN
+ if (::listen(socketDescriptor, backlog) < 0) {
+#else
+ if (qt_safe_listen(socketDescriptor, backlog) < 0) {
+#endif
switch (errno) {
case EADDRINUSE:
setError(QAbstractSocket::AddressInUseError,
@@ -493,12 +554,22 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
int QNativeSocketEnginePrivate::nativeAccept()
{
- int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0);
-#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
+#ifdef Q_OS_SYMBIAN
+ int acceptedDescriptor = ::accept(socketDescriptor, 0, 0);
+#else
+ int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
+#endif
+ //check if we have vaild descriptor at all
+ if(acceptedDescriptor > 0) {
+ // Ensure that the socket is closed on exec*()
+ ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
+ }
+#ifdef Q_OS_SYMBIAN
+ else {
+ qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0");
+ }
#endif
- // Ensure that the socket is closed on exec*()
- ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
+
return acceptedDescriptor;
}
@@ -507,7 +578,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
int nbytes = 0;
// gives shorter than true amounts on Unix domain sockets.
qint64 available = 0;
- if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
+#ifdef Q_OS_SYMBIAN
+ if (::ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
+#else
+ if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
+#endif
available = (qint64) nbytes;
#if defined (QNATIVESOCKETENGINE_DEBUG)
@@ -542,16 +617,25 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
return result;
}
+#ifdef Q_OS_SYMBIAN
+qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
+{
+ size_t nbytes = 0;
+ ::ioctl(socketDescriptor, E32IONREAD, (char *) &nbytes);
+ return qint64(nbytes-28);
+}
+#else
qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
{
QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
ssize_t recvResult = -1;
+
for (;;) {
// the data written to udpMessagePeekBuffer is discarded, so
// this function is still reentrant although it might not look
// so.
recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
- udpMessagePeekBuffer.size(), MSG_PEEK);
+ udpMessagePeekBuffer.size(), MSG_PEEK);
if (recvResult == -1 && errno == EINTR)
continue;
@@ -567,7 +651,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
return qint64(recvResult);
}
-
+#endif
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
QHostAddress *address, quint16 *port)
{
@@ -609,33 +693,34 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
#if !defined(QT_NO_IPV6)
struct sockaddr_in6 sockAddrIPv6;
if (host.protocol() == QAbstractSocket::IPv6Protocol) {
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
-
- Q_IPV6ADDR tmp = host.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
+ memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
+ sockAddrIPv6.sin6_family = AF_INET6;
+ sockAddrIPv6.sin6_port = htons(port);
+
+ Q_IPV6ADDR tmp = host.toIPv6Address();
+ memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
+ sockAddrSize = sizeof(sockAddrIPv6);
+ sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
} else
#endif
if (host.protocol() == QAbstractSocket::IPv4Protocol) {
- memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
- sockAddrIPv4.sin_family = AF_INET;
- sockAddrIPv4.sin_port = htons(port);
- sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
- sockAddrSize = sizeof(sockAddrIPv4);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
+ memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
+ sockAddrIPv4.sin_family = AF_INET;
+ sockAddrIPv4.sin_port = htons(port);
+ sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
+ sockAddrSize = sizeof(sockAddrIPv4);
+ sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
}
// ignore the SIGPIPE signal
qt_ignore_sigpipe();
-
- ssize_t sentBytes;
- do {
- sentBytes = ::sendto(socketDescriptor, data, len,
- 0, sockAddrPtr, sockAddrSize);
- } while (sentBytes == -1 && errno == EINTR);
+#ifdef Q_OS_SYMBIAN
+ ssize_t sentBytes = ::sendto(socketDescriptor, data, len,
+ 0, sockAddrPtr, sockAddrSize);
+#else
+ ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
+ 0, sockAddrPtr, sockAddrSize);
+#endif
if (sentBytes < 0) {
switch (errno) {
@@ -732,7 +817,12 @@ void QNativeSocketEnginePrivate::nativeClose()
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEngine::nativeClose()");
#endif
+
+#ifdef Q_OS_SYMBIAN
::close(socketDescriptor);
+#else
+ qt_safe_close(socketDescriptor);
+#endif
}
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
@@ -746,7 +836,12 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
// of an interrupting signal.
ssize_t writtenBytes;
do {
- writtenBytes = ::write(socketDescriptor, data, len);
+#ifdef Q_OS_SYMBIAN
+ writtenBytes = ::write(socketDescriptor, data, len);
+#else
+ writtenBytes = qt_safe_write(socketDescriptor, data, len);
+#endif
+ // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it?
} while (writtenBytes < 0 && errno == EINTR);
if (writtenBytes < 0) {
@@ -788,7 +883,11 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
ssize_t r = 0;
do {
+#ifdef Q_OS_SYMBIAN
r = ::read(socketDescriptor, data, maxSize);
+#else
+ r = qt_safe_read(socketDescriptor, data, maxSize);
+#endif
} while (r == -1 && errno == EINTR);
if (r < 0) {
@@ -806,7 +905,13 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
case EIO:
setError(QAbstractSocket::NetworkError, ReadErrorString);
break;
+#ifdef Q_OS_SYMBIAN
+ case EPIPE:
+#endif
case ECONNRESET:
+#if defined(Q_OS_VXWORKS)
+ case ESHUTDOWN:
+#endif
r = 0;
break;
default:
@@ -833,38 +938,46 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
- QTime timer;
- timer.start();
+#ifdef Q_OS_SYMBIAN
+ fd_set fdexception;
+ FD_ZERO(&fdexception);
+ FD_SET(socketDescriptor, &fdexception);
+#endif
int retval;
- do {
- if (selectForRead)
- retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
- else
- retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
+ if (selectForRead)
+#ifdef Q_OS_SYMBIAN
+ retval = ::select(socketDescriptor + 1, &fds, 0, &fdexception, timeout < 0 ? 0 : &tv);
+#else
+ retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
+#endif
+ else
+#ifdef Q_OS_SYMBIAN
+ retval = ::select(socketDescriptor + 1, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
+#else
+ retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
+#endif
- if (retval != -1 || errno != EINTR)
- break;
- if (timeout > 0) {
- // recalculate the timeout
- int t = timeout - timer.elapsed();
- if (t < 0) {
- // oops, timeout turned negative?
- retval = -1;
- break;
+#ifdef Q_OS_SYMBIAN
+ bool selectForExec = false;
+ if(retval != 0) {
+ if(retval < 0) {
+ qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
}
-
- tv.tv_sec = t / 1000;
- tv.tv_usec = (t % 1000) * 1000;
+ selectForExec = FD_ISSET(socketDescriptor, &fdexception);
}
- } while (true);
+ if(selectForExec) {
+ qWarning("nativeSelect (selectForRead %d, retVal %d, errno %d) Unexpected exception for fd %d",
+ selectForRead, retval, errno, socketDescriptor);
+ }
+#endif
return retval;
}
int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
- bool *selectForRead, bool *selectForWrite) const
+ bool *selectForRead, bool *selectForWrite) const
{
fd_set fdread;
FD_ZERO(&fdread);
@@ -876,18 +989,48 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c
if (checkWrite)
FD_SET(socketDescriptor, &fdwrite);
+#ifdef Q_OS_SYMBIAN
+ fd_set fdexception;
+ FD_ZERO(&fdexception);
+ FD_SET(socketDescriptor, &fdexception);
+#endif
+
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
+ int ret;
+#ifndef Q_OS_SYMBIAN
+ ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
+#else
QTime timer;
timer.start();
- int ret;
do {
- ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
- if (ret != -1 || errno != EINTR)
+ ret = ::select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
+ bool selectForExec = false;
+ if(ret != 0) {
+ if(ret < 0) {
+ qWarning("nativeSelect(....) returned < 0 for socket %d", socketDescriptor);
+ }
+ selectForExec = FD_ISSET(socketDescriptor, &fdexception);
+ }
+ if(selectForExec) {
+ qWarning("nativeSelect (checkRead %d, checkWrite %d, ret %d, errno %d): Unexpected expectfds ready in fd %d",
+ checkRead, checkWrite, ret, errno, socketDescriptor);
+ if (checkRead)
+ FD_SET(socketDescriptor, &fdread);
+ if (checkWrite)
+ FD_SET(socketDescriptor, &fdwrite);
+
+ if ((ret == -1) && ( errno == ECONNREFUSED || errno == EPIPE ))
+ ret = 1;
+
+ }
+
+ if (ret != -1 || errno != EINTR) {
break;
+ }
if (timeout > 0) {
// recalculate the timeout
@@ -902,11 +1045,13 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c
tv.tv_usec = (t % 1000) * 1000;
}
} while (true);
+#endif
+
if (ret <= 0)
return ret;
-
*selectForRead = FD_ISSET(socketDescriptor, &fdread);
*selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
+
return ret;
}
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index bdc0ed0..655a18f 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -166,11 +166,11 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
Extracts the port and address from a sockaddr, and stores them in
\a port and \a addr if they are non-null.
*/
-static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, struct sockaddr *sa, quint16 *port, QHostAddress *address)
+static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
{
#if !defined (QT_NO_IPV6)
- if (sa->sa_family == AF_INET6) {
- qt_sockaddr_in6 *sa6 = (qt_sockaddr_in6 *)sa;
+ if (sa->a.sa_family == AF_INET6) {
+ const qt_sockaddr_in6 *sa6 = &sa->a6;
Q_IPV6ADDR tmp;
for (int i = 0; i < 16; ++i)
tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
@@ -182,8 +182,8 @@ static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, struct s
WSANtohs(socketDescriptor, sa6->sin6_port, port);
} else
#endif
- if (sa->sa_family == AF_INET) {
- struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
+ if (sa->a.sa_family == AF_INET) {
+ const sockaddr_in *sa4 = &sa->a4;
unsigned long addr;
WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
QHostAddress a;
@@ -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;
}
@@ -463,20 +481,15 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
if (socketDescriptor == -1)
return false;
-#if !defined (QT_NO_IPV6)
- struct qt_sockaddr_storage sa;
-#else
- struct sockaddr_in sa;
-#endif
- struct sockaddr *pSa = (struct sockaddr *) &sa;
-
- QT_SOCKLEN_T sz = sizeof(sa);
+ qt_sockaddr sa;
+ QT_SOCKLEN_T sockAddrSize = sizeof(sa);
+ // Determine local address
memset(&sa, 0, sizeof(sa));
- if (::getsockname(socketDescriptor, pSa, &sz) == 0) {
- qt_socket_getPortAndAddress(socketDescriptor, pSa, &localPort, &localAddress);
+ if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
+ qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
// Determine protocol family
- switch (pSa->sa_family) {
+ switch (sa.a.sa_family) {
case AF_INET:
socketProtocol = QAbstractSocket::IPv4Protocol;
break;
@@ -500,8 +513,8 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
}
memset(&sa, 0, sizeof(sa));
- if (::getpeername(socketDescriptor, pSa, &sz) == 0) {
- qt_socket_getPortAndAddress(socketDescriptor, pSa, &peerPort, &peerAddress);
+ if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
+ qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
} else {
WS_ERROR_DEBUG(WSAGetLastError());
}
@@ -533,8 +546,8 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin
struct sockaddr_in sockAddrIPv4;
qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr;
- QT_SOCKLEN_T sockAddrSize;
+ struct sockaddr *sockAddrPtr = 0;
+ QT_SOCKLEN_T sockAddrSize = 0;
qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
@@ -638,8 +651,8 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
{
struct sockaddr_in sockAddrIPv4;
qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr;
- QT_SOCKLEN_T sockAddrSize;
+ struct sockaddr *sockAddrPtr = 0;
+ QT_SOCKLEN_T sockAddrSize = 0;
qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
@@ -766,20 +779,9 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
{
#if !defined(Q_OS_WINCE)
// Create a sockaddr struct and reset its port number.
-#if !defined(QT_NO_IPV6)
- qt_sockaddr_in6 storage;
- qt_sockaddr_in6 *storagePtrIPv6 = reinterpret_cast<qt_sockaddr_in6 *>(&storage);
- storagePtrIPv6->sin6_port = 0;
-#else
- struct sockaddr storage;
-#endif
- sockaddr *storagePtr = reinterpret_cast<sockaddr *>(&storage);
- storagePtr->sa_family = 0;
-
- sockaddr_in *storagePtrIPv4 = reinterpret_cast<sockaddr_in *>(&storage);
- storagePtrIPv4->sin_port = 0;
+ qt_sockaddr storage;
QT_SOCKLEN_T storageSize = sizeof(storage);
-
+ memset(&storage, 0, storageSize);
bool result = false;
@@ -791,7 +793,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
buf.len = sizeof(c);
DWORD available = 0;
DWORD flags = MSG_PEEK;
- int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, storagePtr, &storageSize,0,0);
+ int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err);
@@ -801,7 +803,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
// notifiers.
flags = 0;
::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
- storagePtr, &storageSize, 0, 0);
+ &storage.a, &storageSize, 0, 0);
}
} else {
// If there's no error, or if our buffer was too small, there must be
@@ -893,14 +895,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
{
qint64 ret = 0;
-#if !defined(QT_NO_IPV6)
- qt_sockaddr_storage aa;
-#else
- struct sockaddr_in aa;
-#endif
+ qt_sockaddr aa;
memset(&aa, 0, sizeof(aa));
QT_SOCKLEN_T sz;
sz = sizeof(aa);
+
WSABUF buf;
buf.buf = data;
buf.len = maxLength;
@@ -915,23 +914,17 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL
DWORD flags = 0;
DWORD bytesRead = 0;
- int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, (struct sockaddr *) &aa, &sz,0,0);
+ int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
if (wsaRet == SOCKET_ERROR) {
int err = WSAGetLastError();
- if (err == WSAEMSGSIZE) {
- // it is ok the buffer was to small if bytesRead is larger than
- // maxLength (win 9x) then assume bytes read is really maxLenth
- ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
- } else {
- WS_ERROR_DEBUG(err);
- setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
- ret = -1;
- }
+ WS_ERROR_DEBUG(err);
+ setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
+ ret = -1;
} else {
ret = qint64(bytesRead);
}
- qt_socket_getPortAndAddress(socketDescriptor, (struct sockaddr *) &aa, port, address);
+ qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li",
@@ -950,41 +943,37 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
qint64 ret = -1;
struct sockaddr_in sockAddrIPv4;
qt_sockaddr_in6 sockAddrIPv6;
- struct sockaddr *sockAddrPtr;
- QT_SOCKLEN_T sockAddrSize;
+ struct sockaddr *sockAddrPtr = 0;
+ QT_SOCKLEN_T sockAddrSize = 0;
qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && len > qint64(qt_socket_getMaxMsgSize(socketDescriptor))) {
- // WSAEMSGSIZE is not reliable enough (win 9x) so we check max size our self.
- setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
- } else {
- WSABUF buf;
+ WSABUF buf;
#if !defined(Q_OS_WINCE)
- buf.buf = len ? (char*)data : 0;
+ buf.buf = len ? (char*)data : 0;
#else
- char tmp;
- buf.buf = len ? (char*)data : &tmp;
+ char tmp;
+ buf.buf = len ? (char*)data : &tmp;
#endif
- buf.len = len;
- DWORD flags = 0;
- DWORD bytesSent = 0;
- if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) {
- int err = WSAGetLastError();
- WS_ERROR_DEBUG(err);
- switch (err) {
- case WSAEMSGSIZE:
- setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
- break;
- default:
- setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
- break;
- }
- ret = -1;
- } else {
- ret = qint64(bytesSent);
+ buf.len = len;
+ DWORD flags = 0;
+ DWORD bytesSent = 0;
+ if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) {
+ int err = WSAGetLastError();
+ WS_ERROR_DEBUG(err);
+ switch (err) {
+ case WSAEMSGSIZE:
+ setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
+ break;
+ default:
+ setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
+ break;
}
+ ret = -1;
+ } else {
+ ret = qint64(bytesSent);
}
+
#if defined (QNATIVESOCKETENGINE_DEBUG)
qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data,
qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(),
diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h
new file mode 100644
index 0000000..1aeb42f
--- /dev/null
+++ b/src/network/socket/qnet_unix_p.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNET_UNIX_P_H
+#define QNET_UNIX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt code on Unix. This header file may change from version to
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qcore_unix_p.h"
+
+#include <sys/types.h>
+#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>
+#if defined(Q_OS_VXWORKS)
+# include <hostLib.h>
+#else
+# include <resolv.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Almost always the same. If not, specify in qplatformdefs.h.
+#if !defined(QT_SOCKOPTLEN_T)
+# define QT_SOCKOPTLEN_T QT_SOCKLEN_T
+#endif
+
+// UnixWare 7 redefines socket -> _socket
+static inline int qt_safe_socket(int domain, int type, int protocol, int flags = 0)
+{
+ Q_ASSERT((flags & ~O_NONBLOCK) == 0);
+
+ register int fd;
+#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ int newtype = type | SOCK_CLOEXEC;
+ if (flags & O_NONBLOCK)
+ newtype |= SOCK_NONBLOCK;
+ fd = ::socket(domain, newtype, protocol);
+ if (fd != -1 || errno != EINVAL)
+ return fd;
+#endif
+
+ fd = ::socket(domain, type, protocol);
+ if (fd == -1)
+ return -1;
+
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ // set non-block too?
+ if (flags & O_NONBLOCK)
+ ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
+
+ return fd;
+}
+
+// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED
+static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags = 0)
+{
+ Q_ASSERT((flags & ~O_NONBLOCK) == 0);
+
+ register int fd;
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
+ // use accept4
+ int sockflags = SOCK_CLOEXEC;
+ if (flags & O_NONBLOCK)
+ sockflags |= SOCK_NONBLOCK;
+ fd = ::accept4(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), sockflags);
+ if (fd != -1 || !(errno == ENOSYS || errno == EINVAL))
+ return fd;
+#endif
+
+ fd = ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen));
+ if (fd == -1)
+ return -1;
+
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ // set non-block too?
+ if (flags & O_NONBLOCK)
+ ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
+
+ return fd;
+}
+
+// UnixWare 7 redefines listen -> _listen
+static inline int qt_safe_listen(int s, int backlog)
+{
+ return ::listen(s, backlog);
+}
+
+static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SOCKLEN_T addrlen)
+{
+ register int ret;
+ // Solaris e.g. expects a non-const 2nd parameter
+ EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, const_cast<struct sockaddr *>(addr), addrlen));
+ return ret;
+}
+#undef QT_SOCKET_CONNECT
+#define QT_SOCKET_CONNECT qt_safe_connect
+
+#if defined(socket)
+# undef socket
+#endif
+#if defined(accept)
+# undef accept
+#endif
+#if defined(listen)
+# 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
+ flags |= MSG_NOSIGNAL;
+#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;
+}
+
+QT_END_NAMESPACE
+
+#endif // QNET_UNIX_P_H
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index ebaa41e..ed84533 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -59,7 +59,11 @@
QT_BEGIN_NAMESPACE
+#ifdef Q_OS_SYMBIAN
+static const int MaxWriteBufferSize = 4*1024;
+#else
static const int MaxWriteBufferSize = 128*1024;
+#endif
//#define QSOCKS5SOCKETLAYER_DEBUG
@@ -153,7 +157,7 @@ static inline QString dump(const QByteArray &) { return QString(); }
*/
static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, quint16 port, QByteArray *pBuf)
{
- QSOCKS5_DEBUG << "setting [" << address << ":" << port << "]";
+ QSOCKS5_DEBUG << "setting [" << address << ':' << port << ']';
union {
quint16 port;
@@ -186,7 +190,7 @@ static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, qui
*/
static bool qt_socks5_set_host_name_and_port(const QString &hostname, quint16 port, QByteArray *pBuf)
{
- QSOCKS5_DEBUG << "setting [" << hostname << ":" << port << "]";
+ QSOCKS5_DEBUG << "setting [" << hostname << ':' << port << ']';
QByteArray encodedHostName = QUrl::toAce(hostname);
QByteArray &buf = *pBuf;
@@ -265,7 +269,7 @@ static bool qt_socks5_get_host_address_and_port(const QByteArray &buf, QHostAddr
}
if (ret) {
- QSOCKS5_DEBUG << "got [" << address << ":" << port << "]";
+ QSOCKS5_DEBUG << "got [" << address << ':' << port << ']';
*pAddress = address;
*pPort = port;
*pPos = pos;
@@ -1124,7 +1128,7 @@ bool QSocks5SocketEngine::connectInternal()
bool QSocks5SocketEngine::connectToHost(const QHostAddress &address, quint16 port)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_DEBUG << "connectToHost" << address << ":" << port;
+ QSOCKS5_DEBUG << "connectToHost" << address << ':' << port;
setPeerAddress(address);
setPeerPort(port);
@@ -1379,7 +1383,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port)
//### reset and error
return false;
}
- QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ":" << d->localPort;
+ QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ':' << d->localPort;
return true;
#endif // QT_NO_UDPSOCKET
}
@@ -1478,7 +1482,7 @@ qint64 QSocks5SocketEngine::bytesAvailable() const
qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ")";
+ QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ')';
if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
if (d->connectData->readBuffer.size() == 0) {
if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) {
@@ -1621,14 +1625,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;
}
@@ -1766,7 +1784,7 @@ void QSocks5SocketEngine::setReadNotificationEnabled(bool enable)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ")";
+ QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ')';
bool emitSignal = false;
if (!d->readNotificationEnabled
@@ -1830,9 +1848,9 @@ QSocks5SocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socke
QSOCKS5_DEBUG << "not proxying";
return 0;
}
- QSocks5SocketEngine *engine = new QSocks5SocketEngine(parent);
+ QScopedPointer<QSocks5SocketEngine> engine(new QSocks5SocketEngine(parent));
engine->setProxy(proxy);
- return engine;
+ return engine.take();
}
QAbstractSocketEngine *QSocks5SocketEngineHandler::createSocketEngine(int socketDescriptor, QObject *parent)
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index 7cb0920..8fb07b5 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index b1c427c..646987a 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\brief The QTcpServer class provides a TCP-based server.
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
This class makes it possible to accept incoming TCP connections.
@@ -354,7 +354,12 @@ void QTcpServer::close()
if (d->socketEngine) {
d->socketEngine->close();
- d->socketEngine->deleteLater();
+ QT_TRY {
+ d->socketEngine->deleteLater();
+ } QT_CATCH(const std::bad_alloc &) {
+ // in out of memory situations, the socketEngine
+ // will be deleted in ~QTcpServer (it's a child-object of this)
+ }
d->socketEngine = 0;
}
diff --git a/src/network/socket/qtcpserver.h b/src/network/socket/qtcpserver.h
index a8bdd16..176933b 100644
--- a/src/network/socket/qtcpserver.h
+++ b/src/network/socket/qtcpserver.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qtcpsocket.cpp b/src/network/socket/qtcpsocket.cpp
index 41c91fc..e04231c 100644
--- a/src/network/socket/qtcpsocket.cpp
+++ b/src/network/socket/qtcpsocket.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -47,7 +47,7 @@
\brief The QTcpSocket class provides a TCP socket.
\reentrant
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
TCP (Transmission Control Protocol) is a reliable,
@@ -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 f349dd6..3005faf 100644
--- a/src/network/socket/qtcpsocket.h
+++ b/src/network/socket/qtcpsocket.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -43,6 +43,7 @@
#define QTCPSOCKET_H
#include <QtNetwork/qabstractsocket.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_HEADER
diff --git a/src/network/socket/qtcpsocket_p.h b/src/network/socket/qtcpsocket_p.h
index 6a53c13..7cbb23a 100644
--- a/src/network/socket/qtcpsocket_p.h
+++ b/src/network/socket/qtcpsocket_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index 9219f19..235003a 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\reentrant
\brief The QUdpSocket class provides a UDP socket.
- \ingroup io
+ \ingroup network
\inmodule QtNetwork
UDP (User Datagram Protocol) is a lightweight, unreliable,
@@ -95,6 +95,13 @@
This enum describes the different flags you can pass to modify the
behavior of QUdpSocket::bind().
+ \note On Symbian OS bind flags behaviour depends on process capabilties.
+ If process has NetworkControl capability, the bind attempt with
+ ReuseAddressHint will always succeed even if the address and port is already
+ bound by another socket with any flags. If process does not have
+ NetworkControl capability, the bind attempt to address and port already
+ bound by another socket will always fail.
+
\value ShareAddress Allow other services to bind to the same address
and port. This is useful when multiple processes share
the load of a single service by listening to the same address and port
@@ -350,6 +357,9 @@ qint64 QUdpSocket::pendingDatagramSize() const
fragmented by the IP layer before arriving at their final
destination.
+ \warning In S60 5.0 and earlier versions, the writeDatagram return
+ value is not reliable for large datagrams.
+
\warning Calling this function on a connected UDP socket may
result in an error and no packet being sent. If you are using a
connected socket, use write() to send datagrams.
@@ -368,6 +378,16 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre
return -1;
qint64 sent = d->socketEngine->writeDatagram(data, size, address, port);
+#ifdef Q_OS_SYMBIAN
+ if( QSysInfo::s60Version() <= QSysInfo::SV_S60_5_0 ) {
+ // This is evil hack, but for some reason native RSocket::SendTo returns 0,
+ // for large datagrams (such as 600 bytes). Based on comments from Open C team
+ // this should happen only in platforms <= S60 5.0.
+ // As an workaround, we just set sent = size
+ if( sent == 0 )
+ sent = size;
+ }
+#endif
d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
if (sent >= 0) {
@@ -380,7 +400,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre
return sent;
}
-/*!
+/*!
\fn qint64 QUdpSocket::writeDatagram(const QByteArray &datagram,
const QHostAddress &host, quint16 port)
\overload
diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h
index e9421a9..6a44d5c 100644
--- a/src/network/socket/qudpsocket.h
+++ b/src/network/socket/qudpsocket.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri
index b1fe64a..2bafe13 100644
--- a/src/network/socket/socket.pri
+++ b/src/network/socket/socket.pri
@@ -28,7 +28,8 @@ SOURCES += socket/qabstractsocketengine.cpp \
unix:SOURCES += socket/qnativesocketengine_unix.cpp \
socket/qlocalsocket_unix.cpp \
socket/qlocalserver_unix.cpp
-
+unix:HEADERS += \
+ socket/qnet_unix_p.h
win32:SOURCES += socket/qnativesocketengine_win.cpp \
socket/qlocalsocket_win.cpp \
@@ -42,5 +43,3 @@ wince*: {
DEFINES += QT_LOCALSOCKET_TCP
}
-
-
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 089d81d..a97f8ed 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE
\brief The QSsl namespace declares enums common to all SSL classes in QtNetwork.
\since 4.3
- \ingroup io
+ \ingroup network
+ \ingroup ssl
\inmodule QtNetwork
*/
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 3654d38..144092c 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 07047bc..3793b1e 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\ingroup ssl
\inmodule QtNetwork
@@ -71,9 +71,10 @@
After loading a certificate, you can find information about the
certificate, its subject, and its issuer, by calling one of the
many accessor functions, including version(), serialNumber(),
- issuerInfo() and subjectInfo(). You can call notValidBefore() and
- notValidAfter() to check when the certificate was issued, and when
- it expires. The publicKey() function returns the certificate
+ issuerInfo() and subjectInfo(). You can call effectiveDate() and
+ expiryDate() to check when the certificate starts being
+ effective and when it expires.
+ The publicKey() function returns the certificate
subject's public key as a QSslKey. You can call issuerInfo() or
subjectInfo() to get detailed information about the certificate
issuer and its subject.
@@ -125,6 +126,9 @@
QT_BEGIN_NAMESPACE
+// forward declaration
+static QMap<QString, QString> _q_mapFromOnelineName(char *name);
+
/*!
Constructs a QSslCertificate by reading \a format encoded data
from \a device and using the first certificate found. You can
@@ -157,7 +161,6 @@ QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat fo
*/
QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d)
{
- d->ref.ref();
}
/*!
@@ -165,8 +168,6 @@ QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d)
*/
QSslCertificate::~QSslCertificate()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -175,7 +176,7 @@ QSslCertificate::~QSslCertificate()
*/
QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
{
- qAtomicAssign(d, other.d);
+ d = other.d;
return *this;
}
@@ -241,11 +242,6 @@ void QSslCertificate::clear()
{
if (isNull())
return;
- if (d->ref == 1)
- delete d;
- else
- d->ref.deref();
-
d = new QSslCertificatePrivate;
}
@@ -254,14 +250,22 @@ void QSslCertificate::clear()
*/
QByteArray QSslCertificate::version() const
{
+ if (d->versionString.isEmpty() && d->x509)
+ d->versionString =
+ QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
+
return d->versionString;
}
/*!
- Returns the certificate's serial number string.
+ Returns the certificate's serial number string in decimal format.
*/
QByteArray QSslCertificate::serialNumber() const
{
+ if (d->serialNumberString.isEmpty() && d->x509)
+ d->serialNumberString =
+ QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber)));
+
return d->serialNumberString;
}
@@ -300,6 +304,10 @@ static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
*/
QString QSslCertificate::issuerInfo(SubjectInfo info) const
{
+ if (d->issuerInfo.isEmpty() && d->x509)
+ d->issuerInfo =
+ _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0));
+
return d->issuerInfo.value(_q_SubjectInfoToString(info));
}
@@ -327,6 +335,10 @@ QString QSslCertificate::issuerInfo(const QByteArray &tag) const
*/
QString QSslCertificate::subjectInfo(SubjectInfo info) const
{
+ if (d->subjectInfo.isEmpty() && d->x509)
+ d->subjectInfo =
+ _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0));
+
return d->subjectInfo.value(_q_SubjectInfoToString(info));
}
@@ -383,7 +395,7 @@ QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubje
else if (genName->type == GEN_EMAIL)
result.insert(QSsl::EmailEntry, altName);
}
- q_sk_free((STACK*)altNames);
+ q_sk_pop_free((STACK*)altNames, q_sk_free);
}
return result;
@@ -662,11 +674,6 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
if (!x509 || !QSslSocket::supportsSsl())
return certificate;
- certificate.d->issuerInfo =
- _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(x509), 0, 0));
- certificate.d->subjectInfo =
- _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(x509), 0, 0));
-
ASN1_TIME *nbef = q_X509_get_notBefore(x509);
ASN1_TIME *naft = q_X509_get_notAfter(x509);
certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
@@ -686,7 +693,7 @@ static bool matchLineFeed(const QByteArray &pem, int *offset)
ch = pem.at(++*offset);
if (ch == '\n') {
- *offset++;
+ *offset += 1;
return true;
}
if (ch == '\r' && pem.size() > (*offset + 1) && pem.at(*offset + 1) == '\n') {
@@ -766,16 +773,16 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
{
debug << "QSslCertificate("
<< certificate.version()
- << "," << certificate.serialNumber()
- << "," << certificate.digest().toBase64()
- << "," << certificate.issuerInfo(QSslCertificate::Organization)
- << "," << certificate.subjectInfo(QSslCertificate::Organization)
- << "," << certificate.alternateSubjectNames()
+ << ',' << certificate.serialNumber()
+ << ',' << certificate.digest().toBase64()
+ << ',' << certificate.issuerInfo(QSslCertificate::Organization)
+ << ',' << certificate.subjectInfo(QSslCertificate::Organization)
+ << ',' << certificate.alternateSubjectNames()
#ifndef QT_NO_TEXTSTREAM
- << "," << certificate.effectiveDate()
- << "," << certificate.expiryDate()
+ << ',' << certificate.effectiveDate()
+ << ',' << certificate.expiryDate()
#endif
- << ")";
+ << ')';
return debug;
}
QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info)
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 2d6e4de..ea34b7d 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -47,6 +47,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qregexp.h>
+#include <QtCore/qsharedpointer.h>
#include <QtNetwork/qssl.h>
typedef struct x509_st X509; // ### check if this works
@@ -118,7 +119,7 @@ public:
Qt::HANDLE handle() const;
private:
- QSslCertificatePrivate *d;
+ QExplicitlySharedDataPointer<QSslCertificatePrivate> d;
friend class QSslCertificatePrivate;
friend class QSslSocketBackendPrivate;
};
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index 4b673ef..456acc6 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -71,7 +71,6 @@ public:
: null(true), x509(0)
{
QSslSocketPrivate::ensureInitialized();
- ref = 1;
}
~QSslCertificatePrivate()
diff --git a/src/network/ssl/qsslcipher.cpp b/src/network/ssl/qsslcipher.cpp
index 28c43f2..969bf0b 100644
--- a/src/network/ssl/qsslcipher.cpp
+++ b/src/network/ssl/qsslcipher.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\ingroup ssl
\inmodule QtNetwork
@@ -103,7 +103,7 @@ QSslCipher::QSslCipher(const QString &name, QSsl::SslProtocol protocol)
QSslCipher::QSslCipher(const QSslCipher &other)
: d(new QSslCipherPrivate)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
}
/*!
@@ -111,7 +111,6 @@ QSslCipher::QSslCipher(const QSslCipher &other)
*/
QSslCipher::~QSslCipher()
{
- delete d;
}
/*!
@@ -120,7 +119,7 @@ QSslCipher::~QSslCipher()
*/
QSslCipher &QSslCipher::operator=(const QSslCipher &other)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
return *this;
}
@@ -231,7 +230,7 @@ QDebug operator<<(QDebug debug, const QSslCipher &cipher)
debug << "QSslCipher(name=" << qPrintable(cipher.name())
<< ", bits=" << cipher.usedBits()
<< ", proto=" << qPrintable(cipher.protocolString())
- << ")";
+ << ')';
return debug;
}
#endif
diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h
index b989a1d..0b34eed 100644
--- a/src/network/ssl/qsslcipher.h
+++ b/src/network/ssl/qsslcipher.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -44,6 +44,7 @@
#define QSSLCIPHER_H
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qssl.h>
QT_BEGIN_HEADER
@@ -78,7 +79,7 @@ public:
QSsl::SslProtocol protocol() const;
private:
- QSslCipherPrivate *d;
+ QScopedPointer<QSslCipherPrivate> d;
friend class QSslSocketBackendPrivate;
};
diff --git a/src/network/ssl/qsslcipher_p.h b/src/network/ssl/qsslcipher_p.h
index ea38d79..f82a40e0 100644
--- a/src/network/ssl/qsslcipher_p.h
+++ b/src/network/ssl/qsslcipher_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index de139f4..550c457 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -66,7 +66,7 @@ template<> void QSharedDataPointer<QSslConfigurationPrivate>::detach()
\reentrant
\inmodule QtNetwork
- \ingroup io
+ \ingroup network
\ingroup ssl
QSslConfiguration is used by Qt networking classes to relay
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index efd5d0d..2245949 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 30c92f3..4573dfd 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp
index 6566ed0..d47c91d 100644
--- a/src/network/ssl/qsslerror.cpp
+++ b/src/network/ssl/qsslerror.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\ingroup ssl
\inmodule QtNetwork
@@ -105,7 +105,33 @@ public:
};
/*!
- Constructs a QSslError object. The two optional arguments specify the \a
+ Constructs a QSslError object with no error and default certificate.
+
+*/
+
+// RVCT compiler in debug build does not like about default values in const-
+// So as an workaround we define all constructor overloads here explicitly
+QSslError::QSslError()
+ : d(new QSslErrorPrivate)
+{
+ d->error = QSslError::NoError;
+ d->certificate = QSslCertificate();
+}
+
+/*!
+ Constructs a QSslError object. The argument specifies the \a
+ error that occurred.
+
+*/
+QSslError::QSslError(SslError error)
+ : d(new QSslErrorPrivate)
+{
+ d->error = error;
+ d->certificate = QSslCertificate();
+}
+
+/*!
+ Constructs a QSslError object. The two arguments specify the \a
error that occurred, and which \a certificate the error relates to.
\sa QSslCertificate
@@ -123,7 +149,7 @@ QSslError::QSslError(SslError error, const QSslCertificate &certificate)
QSslError::QSslError(const QSslError &other)
: d(new QSslErrorPrivate)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
}
/*!
@@ -131,7 +157,6 @@ QSslError::QSslError(const QSslError &other)
*/
QSslError::~QSslError()
{
- delete d;
}
/*!
@@ -141,7 +166,7 @@ QSslError::~QSslError()
*/
QSslError &QSslError::operator=(const QSslError &other)
{
- *d = *other.d;
+ *d.data() = *other.d.data();
return *this;
}
diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h
index 47e3bea..971e452 100644
--- a/src/network/ssl/qsslerror.h
+++ b/src/network/ssl/qsslerror.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -86,8 +86,14 @@ public:
UnspecifiedError = -1
};
- QSslError(SslError error = NoError, const QSslCertificate &certificate = QSslCertificate());
+ // RVCT compiler in debug build does not like about default values in const-
+ // So as an workaround we define all constructor overloads here explicitly
+ QSslError();
+ QSslError(SslError error);
+ QSslError(SslError error, const QSslCertificate &certificate);
+
QSslError(const QSslError &other);
+
~QSslError();
QSslError &operator=(const QSslError &other);
bool operator==(const QSslError &other) const;
@@ -99,7 +105,7 @@ public:
QSslCertificate certificate() const;
private:
- QSslErrorPrivate *d;
+ QScopedPointer<QSslErrorPrivate> d;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/network/ssl/qsslkey.cpp b/src/network/ssl/qsslkey.cpp
index 4ce6888..caa948e 100644
--- a/src/network/ssl/qsslkey.cpp
+++ b/src/network/ssl/qsslkey.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -46,7 +46,7 @@
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\ingroup ssl
\inmodule QtNetwork
@@ -271,7 +271,6 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding
*/
QSslKey::QSslKey(const QSslKey &other) : d(other.d)
{
- d->ref.ref();
}
/*!
@@ -279,8 +278,6 @@ QSslKey::QSslKey(const QSslKey &other) : d(other.d)
*/
QSslKey::~QSslKey()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -291,7 +288,7 @@ QSslKey::~QSslKey()
*/
QSslKey &QSslKey::operator=(const QSslKey &other)
{
- qAtomicAssign(d, other.d);
+ d = other.d;
return *this;
}
@@ -312,10 +309,7 @@ bool QSslKey::isNull() const
*/
void QSslKey::clear()
{
- if (!d->ref.deref()) {
- delete d;
- d = new QSslKeyPrivate;
- }
+ d = new QSslKeyPrivate;
}
/*!
@@ -460,7 +454,7 @@ QDebug operator<<(QDebug debug, const QSslKey &key)
<< (key.type() == QSsl::PublicKey ? "PublicKey" : "PrivateKey")
<< ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA")
<< ", " << key.length()
- << ")";
+ << ')';
return debug;
}
#endif
diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h
index 4703521..1437099 100644
--- a/src/network/ssl/qsslkey.h
+++ b/src/network/ssl/qsslkey.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -45,6 +45,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qsharedpointer.h>
#include <QtNetwork/qssl.h>
QT_BEGIN_HEADER
@@ -58,7 +59,7 @@ QT_MODULE(Network)
template <typename A, typename B> struct QPair;
class QIODevice;
-
+
class QSslKeyPrivate;
class Q_NETWORK_EXPORT QSslKey
{
@@ -92,7 +93,7 @@ public:
inline bool operator!=(const QSslKey &key) const { return !operator==(key); }
private:
- QSslKeyPrivate *d;
+ QExplicitlySharedDataPointer<QSslKeyPrivate> d;
friend class QSslCertificate;
};
diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h
index 555bbe2..2297436 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -69,7 +69,6 @@ public:
, dsa(0)
{
clear();
- ref = 1;
}
inline ~QSslKeyPrivate()
@@ -91,6 +90,9 @@ public:
DSA *dsa;
QAtomicInt ref;
+
+private:
+ Q_DISABLE_COPY(QSslKeyPrivate)
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index ca03ab6..0e0c347 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -49,7 +49,7 @@
\since 4.3
\reentrant
- \ingroup io
+ \ingroup network
\ingroup ssl
\inmodule QtNetwork
@@ -113,8 +113,8 @@
readLine(), or getChar() to read decrypted data from QSslSocket's
internal buffer, and you can call write() or putChar() to write
data back to the peer. QSslSocket will automatically encrypt the
- written data for you, and emit bytesWritten() once the data has
- been written to the peer.
+ written data for you, and emit encryptedBytesWritten() once
+ the data has been written to the peer.
As a convenience, QSslSocket supports QTcpSocket's blocking
functions waitForConnected(), waitForReadyRead(),
@@ -356,7 +356,7 @@ QSslSocket::~QSslSocket()
want to ignore the errors and continue connecting, you must call
ignoreSslErrors(), either from inside a slot function connected to
the sslErrors() signal, or prior to entering encrypted mode. If
- ignoreSslErrors is not called, the connection is dropped, signal
+ ignoreSslErrors() is not called, the connection is dropped, signal
disconnected() is emitted, and QSslSocket returns to the
UnconnectedState.
@@ -397,6 +397,36 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, O
}
/*!
+ \since 4.6
+ \overload
+
+ In addition to the original behaviour of connectToHostEncrypted,
+ this overloaded method enables the usage of a different hostname
+ (\a sslPeerName) for the certificate validation instead of
+ the one used for the TCP connection (\a hostName).
+
+ \sa connectToHostEncrypted()
+*/
+void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QString &sslPeerName, OpenMode mode)
+{
+ Q_D(QSslSocket);
+ if (d->state == ConnectedState || d->state == ConnectingState) {
+ qWarning("QSslSocket::connectToHostEncrypted() called when already connecting/connected");
+ return;
+ }
+
+ d->init();
+ d->autoStartHandshake = true;
+ d->initialized = true;
+ d->verificationPeerName = sslPeerName;
+
+ // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
+ // establish the connection immediately (i.e., first attempt).
+ connectToHost(hostName, port, mode);
+}
+
+/*!
Initializes QSslSocket with the native socket descriptor \a
socketDescriptor. Returns true if \a socketDescriptor is accepted
as a valid socket descriptor; otherwise returns false.
@@ -412,8 +442,8 @@ bool QSslSocket::setSocketDescriptor(int socketDescriptor, SocketState state, Op
{
Q_D(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ","
- << state << "," << openMode << ")";
+ qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ','
+ << state << ',' << openMode << ')';
#endif
if (!d->plainSocket)
d->createPlainSocket(openMode);
@@ -1569,7 +1599,33 @@ void QSslSocket::startServerEncryption()
void QSslSocket::ignoreSslErrors()
{
Q_D(QSslSocket);
- d->ignoreSslErrors = true;
+ d->ignoreAllSslErrors = true;
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ This method tells QSslSocket to ignore only the errors given in \a
+ errors.
+
+ Note that you can set the expected certificate in the SSL error:
+ If, for instance, you want to connect to a server that uses
+ a self-signed certificate, consider the following snippet:
+
+ \snippet doc/src/snippets/code/src_network_ssl_qsslsocket.cpp 6
+
+ Multiple calls to this function will replace the list of errors that
+ were passed in previous calls.
+ You can clear the list of errors you want to ignore by calling this
+ function with an empty list.
+
+ \sa sslErrors()
+*/
+void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
+{
+ Q_D(QSslSocket);
+ d->ignoreErrorsList = errors;
}
/*!
@@ -1585,7 +1641,7 @@ void QSslSocket::connectToHostImplementation(const QString &hostName, quint16 po
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocket::connectToHostImplementation("
- << hostName << "," << port << "," << openMode << ")";
+ << hostName << ',' << port << ',' << openMode << ')';
#endif
if (!d->plainSocket) {
#ifdef QSSLSOCKET_DEBUG
@@ -1659,7 +1715,7 @@ qint64 QSslSocket::readData(char *data, qint64 maxlen)
} while (!d->readBuffer.isEmpty() && readBytes < maxlen);
}
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::readData(" << (void *)data << "," << maxlen << ") ==" << readBytes;
+ qDebug() << "QSslSocket::readData(" << (void *)data << ',' << maxlen << ") ==" << readBytes;
#endif
return readBytes;
}
@@ -1671,7 +1727,7 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
{
Q_D(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::writeData(" << (void *)data << "," << len << ")";
+ qDebug() << "QSslSocket::writeData(" << (void *)data << ',' << len << ')';
#endif
if (d->mode == UnencryptedMode && !d->autoStartHandshake)
return d->plainSocket->write(data, len);
@@ -1689,7 +1745,13 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
\internal
*/
QSslSocketPrivate::QSslSocketPrivate()
- : initialized(false), readyReadEmittedPointer(0), plainSocket(0)
+ : initialized(false)
+ , mode(QSslSocket::UnencryptedMode)
+ , autoStartHandshake(false)
+ , connectionEncrypted(false)
+ , ignoreAllSslErrors(false)
+ , readyReadEmittedPointer(0)
+ , plainSocket(0)
{
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
}
@@ -1709,7 +1771,11 @@ void QSslSocketPrivate::init()
mode = QSslSocket::UnencryptedMode;
autoStartHandshake = false;
connectionEncrypted = false;
- ignoreSslErrors = false;
+ ignoreAllSslErrors = false;
+
+ // we don't want to clear the ignoreErrorsList, so
+ // that it is possible setting it before connecting
+// ignoreErrorsList.clear();
readBuffer.clear();
writeBuffer.clear();
@@ -1976,7 +2042,7 @@ void QSslSocketPrivate::_q_stateChangedSlot(QAbstractSocket::SocketState state)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ")";
+ qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ')';
#endif
q->setSocketState(state);
emit q->stateChanged(state);
@@ -1989,7 +2055,7 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_errorSlot(" << error << ")";
+ qDebug() << "QSslSocket::_q_errorSlot(" << error << ')';
qDebug() << "\tstate =" << q->state();
qDebug() << "\terrorString =" << q->errorString();
#endif
@@ -2024,7 +2090,7 @@ void QSslSocketPrivate::_q_bytesWrittenSlot(qint64 written)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ")";
+ qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ')';
#endif
if (mode == QSslSocket::UnencryptedMode)
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index 43a485c..095c216 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -86,6 +86,7 @@ public:
// Autostarting the SSL client handshake.
void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode mode = ReadWrite);
+ void connectToHostEncrypted(const QString &hostName, quint16 port, const QString &sslPeerName, OpenMode mode = ReadWrite);
bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState,
OpenMode openMode = ReadWrite);
@@ -168,6 +169,7 @@ public:
QList<QSslError> sslErrors() const;
static bool supportsSsl();
+ void ignoreSslErrors(const QList<QSslError> &errors);
public Q_SLOTS:
void startClientEncryption();
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 4d3259b..c7883bc 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -276,7 +276,7 @@ init_context:
if (first)
first = false;
else
- cipherString.append(":");
+ cipherString.append(':');
cipherString.append(cipher.name().toLatin1());
}
@@ -500,7 +500,7 @@ void QSslSocketBackendPrivate::startClientEncryption()
// Start connecting. This will place outgoing data in the BIO, so we
// follow up with calling transmit().
- testConnection();
+ startHandshake();
transmit();
}
@@ -513,7 +513,7 @@ void QSslSocketBackendPrivate::startServerEncryption()
// Start connecting. This will place outgoing data in the BIO, so we
// follow up with calling transmit().
- testConnection();
+ startHandshake();
transmit();
}
@@ -601,7 +601,7 @@ void QSslSocketBackendPrivate::transmit()
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption";
#endif
- if (testConnection()) {
+ if (startHandshake()) {
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocketBackendPrivate::transmit: encryption established";
#endif
@@ -620,7 +620,7 @@ void QSslSocketBackendPrivate::transmit()
}
// If the request is small and the remote host closes the transmission
- // after sending, there's a chance that testConnection() will already
+ // after sending, there's a chance that startHandshake() will already
// have triggered a shutdown.
if (!ssl)
continue;
@@ -720,7 +720,7 @@ static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &c
return error;
}
-bool QSslSocketBackendPrivate::testConnection()
+bool QSslSocketBackendPrivate::startHandshake()
{
Q_Q(QSslSocket);
@@ -761,7 +761,7 @@ bool QSslSocketBackendPrivate::testConnection()
q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR()));
q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocketBackendPrivate::testConnection: error!" << q->errorString();
+ qDebug() << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString();
#endif
emit q->error(QAbstractSocket::SslHandshakeFailedError);
q->abort();
@@ -792,7 +792,7 @@ bool QSslSocketBackendPrivate::testConnection()
// but only if we're a client connecting to a server
// if we're the server, don't check CN
if (mode == QSslSocket::SslClientMode) {
- QString peerName = q->peerName();
+ QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard);
@@ -839,7 +839,27 @@ bool QSslSocketBackendPrivate::testConnection()
if (!errors.isEmpty()) {
sslErrors = errors;
emit q->sslErrors(errors);
- if (doVerifyPeer && !ignoreSslErrors) {
+
+ bool doEmitSslError;
+ if (!ignoreErrorsList.empty()) {
+ // check whether the errors we got are all in the list of expected errors
+ // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
+ // was called)
+ doEmitSslError = false;
+ for (int a = 0; a < errors.count(); a++) {
+ if (!ignoreErrorsList.contains(errors.at(a))) {
+ doEmitSslError = true;
+ break;
+ }
+ }
+ } else {
+ // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
+ // we get an SSL error, emit a signal unless we ignored all errors (by calling
+ // QSslSocket::ignoreSslErrors() )
+ doEmitSslError = !ignoreAllSslErrors;
+ }
+ // check whether we need to emit an SSL handshake error
+ if (doVerifyPeer && doEmitSslError) {
q->setErrorString(sslErrors.first().errorString());
q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
emit q->error(QAbstractSocket::SslHandshakeFailedError);
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index 728893e..fbd4b69 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -57,7 +57,7 @@
#include "qsslsocket_p.h"
#ifdef Q_OS_WIN
-#include <windows.h>
+#include <qt_windows.h>
#if defined(OCSP_RESPONSE)
#undef OCSP_RESPONSE
#endif
@@ -77,6 +77,8 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/x509_vfy.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
typedef _STACK STACK;
@@ -106,7 +108,7 @@ public:
void startClientEncryption();
void startServerEncryption();
void transmit();
- bool testConnection();
+ bool startHandshake();
void disconnectFromHost();
void disconnected();
QSslCipher sessionCipher() const;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 33567b8..d3dcd51 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -94,6 +94,7 @@ QT_BEGIN_NAMESPACE
#ifdef SSLEAY_MACROS
DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
#endif
+DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
@@ -144,6 +145,7 @@ DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
+DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(STACK*), b, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
#else
@@ -254,10 +256,16 @@ DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c,
DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
+#ifdef Q_OS_SYMBIAN
+#define RESOLVEFUNC(func, ordinal, lib) \
+ if (!(_q_##func = _q_PTR_##func(lib->resolve(#ordinal)))) \
+ qWarning("QSslSocket: cannot resolve "#func);
+#else
#define RESOLVEFUNC(func) \
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
&& !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \
qWarning("QSslSocket: cannot resolve "#func);
+#endif
#if !defined QT_LINKED_OPENSSL
@@ -358,7 +366,24 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
pair.first = ssleay32;
pair.second = libeay32;
return pair;
+# elif defined(Q_OS_SYMBIAN)
+ QLibrary *libssl = new QLibrary(QLatin1String("libssl"));
+ if (!libssl->load()) {
+ // Cannot find ssleay32.dll
+ delete libssl;
+ return pair;
+ }
+ QLibrary *libcrypto = new QLibrary(QLatin1String("libcrypto"));
+ if (!libcrypto->load()) {
+ delete libcrypto;
+ delete libssl;
+ return pair;
+ }
+
+ pair.first = libssl;
+ pair.second = libcrypto;
+ return pair;
# elif defined(Q_OS_UNIX)
QLibrary *&libssl = pair.first;
QLibrary *&libcrypto = pair.second;
@@ -460,9 +485,131 @@ bool q_resolveOpenSslSymbols()
// failed to load them
return false;
+#ifdef Q_OS_SYMBIAN
+#ifdef SSLEAY_MACROS
+ RESOLVEFUNC(ASN1_dup, 125, libs.second )
+#endif
+ RESOLVEFUNC(ASN1_STRING_data, 71, libs.second )
+ RESOLVEFUNC(ASN1_STRING_length, 76, libs.second )
+ RESOLVEFUNC(BIO_ctrl, 184, libs.second )
+ RESOLVEFUNC(BIO_free, 209, libs.second )
+ RESOLVEFUNC(BIO_new, 222, libs.second )
+ RESOLVEFUNC(BIO_new_mem_buf, 230, libs.second )
+ RESOLVEFUNC(BIO_read, 244, libs.second )
+ RESOLVEFUNC(BIO_s_mem, 251, libs.second )
+ RESOLVEFUNC(BIO_write, 269, libs.second )
+ RESOLVEFUNC(BN_num_bits, 387, libs.second )
+ RESOLVEFUNC(CRYPTO_free, 469, libs.second )
+ RESOLVEFUNC(CRYPTO_num_locks, 500, libs.second )
+ RESOLVEFUNC(CRYPTO_set_id_callback, 513, libs.second )
+ RESOLVEFUNC(CRYPTO_set_locking_callback, 516, libs.second )
+ RESOLVEFUNC(DSA_free, 594, libs.second )
+ RESOLVEFUNC(ERR_error_string, 744, libs.second )
+ RESOLVEFUNC(ERR_get_error, 749, libs.second )
+ RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second )
+ RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second )
+ RESOLVEFUNC(EVP_PKEY_free, 867, libs.second )
+ RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second )
+ RESOLVEFUNC(EVP_PKEY_get1_RSA, 870, libs.second )
+ RESOLVEFUNC(EVP_PKEY_new, 876, libs.second )
+ RESOLVEFUNC(EVP_PKEY_type, 882, libs.second )
+ RESOLVEFUNC(OBJ_nid2sn, 1036, libs.second )
+ RESOLVEFUNC(OBJ_obj2nid, 1037, libs.second )
+#ifdef SSLEAY_MACROS // ### verify
+ RESOLVEFUNC(PEM_ASN1_read_bio, 1180, libs.second )
+#else
+ RESOLVEFUNC(PEM_read_bio_DSAPrivateKey, 1219, libs.second )
+ RESOLVEFUNC(PEM_read_bio_RSAPrivateKey, 1228, libs.second )
+ RESOLVEFUNC(PEM_write_bio_DSAPrivateKey, 1260, libs.second )
+ RESOLVEFUNC(PEM_write_bio_RSAPrivateKey, 1271, libs.second )
+#endif
+ RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY, 1220, libs.second )
+ RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY, 1230, libs.second )
+ RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY, 1261, libs.second )
+ RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY, 1273, libs.second )
+ RESOLVEFUNC(RAND_seed, 1426, libs.second )
+ RESOLVEFUNC(RAND_status, 1429, libs.second )
+ RESOLVEFUNC(RSA_free, 1450, libs.second )
+ RESOLVEFUNC(sk_free, 2571, libs.second )
+ RESOLVEFUNC(sk_num, 2576, libs.second )
+ RESOLVEFUNC(sk_value, 2585, libs.second )
+ RESOLVEFUNC(SSL_CIPHER_description, 11, libs.first )
+ RESOLVEFUNC(SSL_CTX_check_private_key, 21, libs.first )
+ RESOLVEFUNC(SSL_CTX_ctrl, 22, libs.first )
+ RESOLVEFUNC(SSL_CTX_free, 24, libs.first )
+ RESOLVEFUNC(SSL_CTX_new, 35, libs.first )
+ RESOLVEFUNC(SSL_CTX_set_cipher_list, 40, libs.first )
+ RESOLVEFUNC(SSL_CTX_set_default_verify_paths, 44, libs.first )
+ RESOLVEFUNC(SSL_CTX_set_verify, 56, libs.first )
+ RESOLVEFUNC(SSL_CTX_set_verify_depth, 57, libs.first )
+ RESOLVEFUNC(SSL_CTX_use_certificate, 64, libs.first )
+ RESOLVEFUNC(SSL_CTX_use_certificate_file, 67, libs.first )
+ RESOLVEFUNC(SSL_CTX_use_PrivateKey, 58, libs.first )
+ RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey, 61, libs.first )
+ RESOLVEFUNC(SSL_CTX_use_PrivateKey_file, 60, libs.first )
+ RESOLVEFUNC(SSL_accept, 82, libs.first )
+ RESOLVEFUNC(SSL_clear, 92, libs.first )
+ RESOLVEFUNC(SSL_connect, 93, libs.first )
+ RESOLVEFUNC(SSL_free, 99, libs.first )
+ RESOLVEFUNC(SSL_get_ciphers, 104, libs.first )
+ RESOLVEFUNC(SSL_get_current_cipher, 106, libs.first )
+ RESOLVEFUNC(SSL_get_error, 110, libs.first )
+ RESOLVEFUNC(SSL_get_peer_cert_chain, 117, libs.first )
+ RESOLVEFUNC(SSL_get_peer_certificate, 118, libs.first )
+ RESOLVEFUNC(SSL_get_verify_result, 132, libs.first )
+ RESOLVEFUNC(SSL_library_init, 137, libs.first )
+ RESOLVEFUNC(SSL_load_error_strings, 139, libs.first )
+ RESOLVEFUNC(SSL_new, 140, libs.first )
+ RESOLVEFUNC(SSL_read, 143, libs.first )
+ RESOLVEFUNC(SSL_set_accept_state, 148, libs.first )
+ RESOLVEFUNC(SSL_set_bio, 149, libs.first )
+ RESOLVEFUNC(SSL_set_connect_state, 152, libs.first )
+ RESOLVEFUNC(SSL_shutdown, 173, libs.first )
+ RESOLVEFUNC(SSL_write, 188, libs.first )
+ RESOLVEFUNC(SSLv2_client_method, 192, libs.first )
+ RESOLVEFUNC(SSLv3_client_method, 195, libs.first )
+ RESOLVEFUNC(SSLv23_client_method, 189, libs.first )
+ RESOLVEFUNC(TLSv1_client_method, 198, libs.first )
+ RESOLVEFUNC(SSLv2_server_method, 194, libs.first )
+ RESOLVEFUNC(SSLv3_server_method, 197, libs.first )
+ RESOLVEFUNC(SSLv23_server_method, 191, libs.first )
+ RESOLVEFUNC(TLSv1_server_method, 200, libs.first )
+ RESOLVEFUNC(X509_NAME_oneline, 1830, libs.second )
+ RESOLVEFUNC(X509_PUBKEY_get, 1844, libs.second )
+ RESOLVEFUNC(X509_STORE_free, 1939, libs.second )
+ RESOLVEFUNC(X509_STORE_new, 1942, libs.second )
+ RESOLVEFUNC(X509_STORE_add_cert, 1936, libs.second )
+ RESOLVEFUNC(X509_STORE_CTX_free, 1907, libs.second )
+ RESOLVEFUNC(X509_STORE_CTX_init, 1919, libs.second )
+ RESOLVEFUNC(X509_STORE_CTX_new, 1920, libs.second )
+ RESOLVEFUNC(X509_STORE_CTX_set_purpose, 1931, libs.second )
+ RESOLVEFUNC(X509_cmp, 1992, libs.second )
+#ifndef SSLEAY_MACROS
+ RESOLVEFUNC(X509_dup, 1997, libs.second )
+#endif
+ RESOLVEFUNC(X509_EXTENSION_get_object, 1785, libs.second )
+ RESOLVEFUNC(X509_free, 2001, libs.second )
+ RESOLVEFUNC(X509_get_ext, 2012, libs.second )
+ RESOLVEFUNC(X509_get_ext_count, 2016, libs.second )
+ RESOLVEFUNC(X509_get_ext_d2i, 2017, libs.second )
+ RESOLVEFUNC(X509_get_issuer_name, 2018, libs.second )
+ RESOLVEFUNC(X509_get_subject_name, 2022, libs.second )
+ RESOLVEFUNC(X509_verify_cert, 2069, libs.second )
+ RESOLVEFUNC(d2i_X509, 2309, libs.second )
+ RESOLVEFUNC(i2d_X509, 2489, libs.second )
+#ifdef SSLEAY_MACROS
+ RESOLVEFUNC(i2d_DSAPrivateKey, 2395, libs.second )
+ RESOLVEFUNC(i2d_RSAPrivateKey, 2476, libs.second )
+ RESOLVEFUNC(d2i_DSAPrivateKey, 2220, libs.second )
+ RESOLVEFUNC(d2i_RSAPrivateKey, 2296, libs.second )
+#endif
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf, 1153, libs.second )
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_conf, 1152, libs.second )
+#else // Q_OS_SYMBIAN
#ifdef SSLEAY_MACROS
RESOLVEFUNC(ASN1_dup)
#endif
+ RESOLVEFUNC(ASN1_INTEGER_get)
RESOLVEFUNC(ASN1_STRING_data)
RESOLVEFUNC(ASN1_STRING_length)
RESOLVEFUNC(BIO_ctrl)
@@ -506,6 +653,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(RSA_free)
RESOLVEFUNC(sk_free)
RESOLVEFUNC(sk_num)
+ RESOLVEFUNC(sk_pop_free)
RESOLVEFUNC(sk_value)
RESOLVEFUNC(SSL_CIPHER_description)
RESOLVEFUNC(SSL_CTX_check_private_key)
@@ -579,6 +727,7 @@ bool q_resolveOpenSslSymbols()
#endif
RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
+#endif // Q_OS_SYMBIAN
symbolsResolved = true;
delete libs.first;
delete libs.second;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 1bcbb53..30762ca 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -201,6 +201,7 @@ QT_BEGIN_NAMESPACE
#endif // !defined QT_LINKED_OPENSSL
bool q_resolveOpenSslSymbols();
+long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
int q_ASN1_STRING_length(ASN1_STRING *a);
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
@@ -256,6 +257,7 @@ int q_RAND_status();
void q_RSA_free(RSA *a);
void q_sk_free(STACK *a);
int q_sk_num(STACK *a);
+void q_sk_pop_free(STACK *a, void (*b)(STACK *));
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
void * q_sk_value(STACK *a, int b);
#else
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 3dadc39..1fac14f 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -21,9 +20,10 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
+** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
@@ -79,7 +79,8 @@ public:
QSslSocket::SslMode mode;
bool autoStartHandshake;
bool connectionEncrypted;
- bool ignoreSslErrors;
+ bool ignoreAllSslErrors;
+ QList<QSslError> ignoreErrorsList;
bool* readyReadEmittedPointer;
QRingBuffer readBuffer;
@@ -88,6 +89,10 @@ public:
QSslConfigurationPrivate configuration;
QList<QSslError> sslErrors;
+ // if set, this hostname is used for certificate validation instead of the hostname
+ // that was used for connecting to.
+ QString verificationPeerName;
+
static bool ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 196e19d..72ea80f 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -1,6 +1,12 @@
# OpenSSL support; compile in QSslSocket.
contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
- include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri)
+
+
+symbian {
+ INCLUDEPATH *= $$OS_LAYER_SSL_SYSTEMINCLUDE
+} else {
+ include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri)
+}
HEADERS += ssl/qssl.h \
ssl/qsslcertificate.h \
@@ -29,5 +35,5 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
RESOURCES += network.qrc
# Add optional SSL libs
- LIBS += $$OPENSSL_LIBS
+ LIBS_PRIVATE += $$OPENSSL_LIBS
}