summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-04-10 12:48:01 +0200
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2012-04-10 15:31:45 +0200
commit143c4d3e13a430b951f4f4f8c28db14303f80605 (patch)
tree2b89637b93fc7d81c674106008566010f986d67c /src/network
parenta7ed81b557d593a8ddb43b71bf4bbf3b44ead070 (diff)
parente5337ad1b1fb02873ce7b5ca8db45f6fd8063352 (diff)
Merge remote-tracking branch 'origin/master' into api_changes
Conflicts: configure src/widgets/styles/qwindowsxpstyle.cpp tests/auto/gui/kernel/qwindow/qwindow.pro tests/auto/gui/kernel/qwindow/tst_qwindow.cpp Change-Id: I624b6d26abce9874c610c04954c1c45bc074bef3
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp10
-rw-r--r--src/network/access/qhttpnetworkreply.cpp23
-rw-r--r--src/network/access/qhttpnetworkreply_p.h1
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp5
-rw-r--r--src/network/access/qnetworkcookie.cpp2
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp2
-rw-r--r--src/network/kernel/qnetworkinterface_win_p.h3
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp48
-rw-r--r--src/network/socket/qabstractsocket.cpp11
-rw-r--r--src/network/socket/qnativesocketengine.cpp13
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp8
-rw-r--r--src/network/socket/qudpsocket.cpp4
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp26
13 files changed, 140 insertions, 16 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index d4931bd207..6e33836feb 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -733,14 +733,8 @@ void QHttpNetworkConnectionChannel::allDone()
}
} else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) {
// this is weird. we had nothing pipelined but still bytes available. better close it.
- //if (socket->bytesAvailable() > 0)
- // close();
- //
- // FIXME
- // We do not close it anymore now, but should introduce this again after having fixed
- // the chunked decoder in QHttpNetworkReply to read the whitespace after the last chunk.
- // (Currently this is worked around by readStatus in the QHttpNetworkReply ignoring
- // leading whitespace.
+ close();
+
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
} else if (alreadyPipelinedRequests.isEmpty()) {
if (connectionCloseEnabled)
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 85463ee210..39204163f2 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -257,6 +257,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
chunkedTransferEncoding(false),
connectionCloseEnabled(true),
forceConnectionCloseEnabled(false),
+ lastChunkRead(false),
currentChunkSize(0), currentChunkRead(0), connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), downstreamLimited(false)
@@ -277,6 +278,7 @@ void QHttpNetworkReplyPrivate::clearHttpLayerInformation()
totalProgress = 0;
currentChunkSize = 0;
currentChunkRead = 0;
+ lastChunkRead = false;
connectionCloseEnabled = true;
#ifndef QT_NO_COMPRESS
if (autoDecompress)
@@ -721,7 +723,7 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, Q
{
qint64 bytes = 0;
while (socket->bytesAvailable()) {
- if (currentChunkRead >= currentChunkSize) {
+ if (!lastChunkRead && currentChunkRead >= currentChunkSize) {
// For the first chunk and when we're done with a chunk
currentChunkSize = 0;
currentChunkRead = 0;
@@ -744,8 +746,23 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, Q
break;
}
// if the chunk size is 0, end of the stream
- if (currentChunkSize == 0) {
- state = AllDoneState;
+ if (currentChunkSize == 0 || lastChunkRead) {
+ lastChunkRead = true;
+ // try to read the "\r\n" after the chunk
+ char crlf[2];
+ qint64 haveRead = socket->read(crlf, 2);
+ if (haveRead > 0)
+ bytes += haveRead;
+
+ if ((haveRead == 2 && crlf[0] == '\r' && crlf[1] == '\n') || (haveRead == 1 && crlf[0] == '\n'))
+ state = AllDoneState;
+ else if (haveRead == 1 && crlf[0] == '\r')
+ break; // Still waiting for the last \n
+ else if (haveRead > 0) {
+ // If we read something else then CRLF, we need to close the channel.
+ forceConnectionCloseEnabled = true;
+ state = AllDoneState;
+ }
break;
}
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 04e4569457..97fefc6e1b 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -217,6 +217,7 @@ public:
bool chunkedTransferEncoding;
bool connectionCloseEnabled;
bool forceConnectionCloseEnabled;
+ bool lastChunkRead;
qint64 currentChunkSize;
qint64 currentChunkRead;
QPointer<QHttpNetworkConnection> connection;
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index 42201aa9a3..4aa491db0c 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -223,6 +223,7 @@ void QNetworkAccessFtpBackend::ftpDone()
if (ftp->state() == QFtp::Connected) {
// the login did not succeed
QUrl newUrl = url();
+ QString userInfo = newUrl.userInfo();
newUrl.setUserInfo(QString());
setUrl(newUrl);
@@ -236,6 +237,10 @@ void QNetworkAccessFtpBackend::ftpDone()
return;
}
+ // Re insert the user info so that we can remove the cache entry.
+ newUrl.setUserInfo(userInfo);
+ setUrl(newUrl);
+
error(QNetworkReply::AuthenticationRequiredError,
tr("Logging in to %1 failed: authentication required")
.arg(url().host()));
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index 0dbfdb2f0c..7174acc31e 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -606,7 +606,7 @@ static bool checkStaticArray(int &val, const QByteArray &dateString, int at, con
val = j;
return true;
}
- i += strlen(str) + 1;
+ i += int(strlen(str)) + 1;
++j;
}
}
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index a311af7686..8e3b5ce7c0 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -182,6 +182,8 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
iface->flags |= QNetworkInterface::IsUp | QNetworkInterface::IsRunning;
if ((ptr->Flags & IP_ADAPTER_NO_MULTICAST) == 0)
iface->flags |= QNetworkInterface::CanMulticast;
+ if (ptr->IfType == IF_TYPE_PPP)
+ iface->flags |= QNetworkInterface::IsPointToPoint;
iface->name = QString::fromLocal8Bit(ptr->AdapterName);
iface->friendlyName = QString::fromWCharArray(ptr->FriendlyName);
diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h
index 73e5c625ec..303f4d3690 100644
--- a/src/network/kernel/qnetworkinterface_win_p.h
+++ b/src/network/kernel/qnetworkinterface_win_p.h
@@ -94,6 +94,9 @@ QT_BEGIN_NAMESPACE
# define MIB_IF_TYPE_LOOPBACK 24
# define MIB_IF_TYPE_SLIP 28
+// definitions from Ipifcons.h
+#define IF_TYPE_PPP 23
+
#endif
// copied from qnativesocketengine_win.cpp
struct qt_in6_addr {
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index 4f1dece4a9..a17f547742 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -113,13 +113,49 @@ typedef HINTERNET (WINAPI * PtrWinHttpOpen)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR,DWO
typedef BOOL (WINAPI * PtrWinHttpGetDefaultProxyConfiguration)(WINHTTP_PROXY_INFO*);
typedef BOOL (WINAPI * PtrWinHttpGetIEProxyConfigForCurrentUser)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*);
typedef BOOL (WINAPI * PtrWinHttpCloseHandle)(HINTERNET);
+typedef SC_HANDLE (WINAPI * PtrOpenSCManager)(LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess);
+typedef BOOL (WINAPI * PtrEnumServicesStatusEx)(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
+ LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName);
+typedef BOOL (WINAPI * PtrCloseServiceHandle)(SC_HANDLE hSCObject);
static PtrWinHttpGetProxyForUrl ptrWinHttpGetProxyForUrl = 0;
static PtrWinHttpOpen ptrWinHttpOpen = 0;
static PtrWinHttpGetDefaultProxyConfiguration ptrWinHttpGetDefaultProxyConfiguration = 0;
static PtrWinHttpGetIEProxyConfigForCurrentUser ptrWinHttpGetIEProxyConfigForCurrentUser = 0;
static PtrWinHttpCloseHandle ptrWinHttpCloseHandle = 0;
+static PtrOpenSCManager ptrOpenSCManager = 0;
+static PtrEnumServicesStatusEx ptrEnumServicesStatusEx = 0;
+static PtrCloseServiceHandle ptrCloseServiceHandle = 0;
+static bool currentProcessIsService()
+{
+ if (!ptrOpenSCManager || !ptrEnumServicesStatusEx|| !ptrCloseServiceHandle)
+ return false;
+
+ SC_HANDLE hSCM = ptrOpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
+ if (!hSCM)
+ return false;
+
+ ULONG bufSize = 0;
+ ULONG nbServices = 0;
+ if (ptrEnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, 0, bufSize, &bufSize, &nbServices, 0, 0))
+ return false; //error case
+
+ LPENUM_SERVICE_STATUS_PROCESS info = reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESS>(malloc(bufSize));
+ bool foundService = false;
+ if (ptrEnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, (LPBYTE)info, bufSize, &bufSize, &nbServices, 0, 0)) {
+ DWORD currProcId = GetCurrentProcessId();
+ for (ULONG i = 0; i < nbServices && !foundService; i++) {
+ if (info[i].ServiceStatusProcess.dwProcessId == currProcId)
+ foundService = true;
+ }
+ }
+
+ ptrCloseServiceHandle(hSCM);
+ free(info);
+ return foundService;
+}
+
static QStringList splitSpaceSemicolon(const QString &source)
{
QStringList list;
@@ -364,10 +400,14 @@ void QWindowsSystemProxy::init()
ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)lib.resolve("WinHttpGetProxyForUrl");
ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)lib.resolve("WinHttpGetDefaultProxyConfiguration");
ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)lib.resolve("WinHttpGetIEProxyConfigForCurrentUser");
+ ptrOpenSCManager = (PtrOpenSCManager) QSystemLibrary(L"advapi32").resolve("OpenSCManagerW");
+ ptrEnumServicesStatusEx = (PtrEnumServicesStatusEx) QSystemLibrary(L"advapi32").resolve("EnumServicesStatusExW");
+ ptrCloseServiceHandle = (PtrCloseServiceHandle) QSystemLibrary(L"advapi32").resolve("CloseServiceHandle");
// Try to obtain the Internet Explorer configuration.
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig;
- if (ptrWinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig)) {
+ const bool hasIEConfig = ptrWinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig);
+ if (hasIEConfig) {
if (ieProxyConfig.lpszAutoConfigUrl) {
autoConfigUrl = QString::fromWCharArray(ieProxyConfig.lpszAutoConfigUrl);
GlobalFree(ieProxyConfig.lpszAutoConfigUrl);
@@ -383,9 +423,13 @@ void QWindowsSystemProxy::init()
proxyBypass = splitSpaceSemicolon(QString::fromWCharArray(ieProxyConfig.lpszProxyBypass));
GlobalFree(ieProxyConfig.lpszProxyBypass);
}
- } else {
+ }
+
+ if (!hasIEConfig ||
+ (currentProcessIsService() && proxyServerList.isEmpty() && proxyBypass.isEmpty())) {
// no user configuration
// attempt to get the default configuration instead
+ // that config will serve as default if WPAD fails
WINHTTP_PROXY_INFO proxyInfo;
if (ptrWinHttpGetDefaultProxyConfiguration(&proxyInfo) &&
proxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY) {
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index af22b20b21..0c4eed8de9 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -1984,7 +1984,16 @@ bool QAbstractSocket::waitForConnected(int msecs)
d->_q_startConnecting(QHostInfoPrivate::fromName(d->hostName, networkSession));
} else
#endif
- d->_q_startConnecting(QHostInfo::fromName(d->hostName));
+ {
+ QHostAddress temp;
+ if (temp.setAddress(d->hostName)) {
+ QHostInfo info;
+ info.setAddresses(QList<QHostAddress>() << temp);
+ d->_q_startConnecting(info);
+ } else {
+ d->_q_startConnecting(QHostInfo::fromName(d->hostName));
+ }
+ }
}
if (state() == UnconnectedState)
return false; // connect not im progress anymore!
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index a34b19f7ef..8fac3613c0 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -637,6 +637,19 @@ bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress,
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false);
Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false);
Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false);
+
+ // if the user binds a socket to an IPv6 address (or QHostAddress::Any) and
+ // then attempts to join an IPv4 multicast group, this won't work on
+ // Windows. In order to make this cross-platform, we warn & fail on all
+ // platforms.
+ if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol &&
+ (d->socketProtocol == QAbstractSocket::IPv6Protocol ||
+ d->socketProtocol == QAbstractSocket::AnyIPProtocol)) {
+ qWarning("QAbstractSocket: cannot bind to QHostAddress::Any (or an IPv6 address) and join an IPv4 multicast group");
+ qWarning("QAbstractSocket: bind to QHostAddress::AnyIPv4 instead if you want to do this");
+ return false;
+ }
+
return d->nativeJoinMulticastGroup(groupAddress, iface);
}
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 295d3961a8..7cd8e1bff3 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -321,7 +321,13 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
}
case QNativeSocketEngine::AddressReusable:
#if defined(SO_REUSEPORT)
- n = SO_REUSEPORT;
+ // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
+ // same port (which is useful for multicast UDP). SO_REUSEPORT is, but
+ // we most definitely do not want to use this for TCP. See QTBUG-6305.
+ if (socketType == QAbstractSocket::UdpSocket)
+ n = SO_REUSEPORT;
+ else
+ n = SO_REUSEADDR;
#else
n = SO_REUSEADDR;
#endif
diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp
index ec751c289e..23c1956ec5 100644
--- a/src/network/socket/qudpsocket.cpp
+++ b/src/network/socket/qudpsocket.cpp
@@ -178,6 +178,10 @@ QUdpSocket::~QUdpSocket()
interface chosen by the operating system. The socket must be in BoundState,
otherwise an error occurs.
+ Note that if you are attempting to join an IPv4 group, your socket must not
+ be bound using IPv6 (or in dual mode, using QHostAddress::Any). You must use
+ QHostAddress::AnyIPv4 instead.
+
This function returns true if successful; otherwise it returns false
and sets the socket error accordingly.
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index aa25215755..b5374d13cd 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -53,6 +53,9 @@
#if defined(Q_OS_UNIX)
#include <QtCore/qdir.h>
#endif
+#ifdef Q_OS_LINUX
+#include <link.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -347,6 +350,23 @@ static bool libGreaterThan(const QString &lhs, const QString &rhs)
return true;
}
+#ifdef Q_OS_LINUX
+static int dlIterateCallback(struct dl_phdr_info *info, size_t size, void *data)
+{
+ if (size < sizeof (info->dlpi_addr) + sizeof (info->dlpi_name))
+ return 1;
+ QSet<QString> *paths = (QSet<QString> *)data;
+ QString path = QString::fromLocal8Bit(info->dlpi_name);
+ if (!path.isEmpty()) {
+ QFileInfo fi(path);
+ path = fi.absolutePath();
+ if (!path.isEmpty())
+ paths->insert(path);
+ }
+ return 0;
+}
+#endif
+
static QStringList findAllLibSsl()
{
QStringList paths;
@@ -358,6 +378,12 @@ static QStringList findAllLibSsl()
.split(QLatin1Char(':'), QString::SkipEmptyParts);
# endif
paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
+#ifdef Q_OS_LINUX
+ // discover paths of already loaded libraries
+ QSet<QString> loadedPaths;
+ dl_iterate_phdr(dlIterateCallback, &loadedPaths);
+ paths.append(loadedPaths.toList());
+#endif
QStringList foundSsls;
foreach (const QString &path, paths) {