diff options
author | David Boddie <dboddie@trolltech.com> | 2009-07-07 13:00:14 (GMT) |
---|---|---|
committer | David Boddie <dboddie@trolltech.com> | 2009-07-07 13:00:14 (GMT) |
commit | f5392a4290e5f7ae2bdf268c1fa8c037e776fdae (patch) | |
tree | d3cc657639b8784dbc22eae2bae5e58e62db7a2f /src/network | |
parent | 0044b3c968f5023f502e3574c96d4e4df0de865d (diff) | |
parent | 2a834d39a69430058df3916392afab064ca941ee (diff) | |
download | Qt-f5392a4290e5f7ae2bdf268c1fa8c037e776fdae.zip Qt-f5392a4290e5f7ae2bdf268c1fa8c037e776fdae.tar.gz Qt-f5392a4290e5f7ae2bdf268c1fa8c037e776fdae.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/network/socket/qlocalsocket.cpp
Diffstat (limited to 'src/network')
20 files changed, 380 insertions, 251 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 365ae8b..f1da244 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -146,7 +146,9 @@ int QHttpNetworkConnectionPrivate::indexOf(QAbstractSocket *socket) const for (int i = 0; i < channelCount; ++i) if (channels[i].socket == socket) return i; - return -1; + + qFatal("Called with unknown socket object."); + return 0; } bool QHttpNetworkConnectionPrivate::isSocketBusy(QAbstractSocket *socket) const @@ -176,7 +178,8 @@ bool QHttpNetworkConnectionPrivate::isSocketReading(QAbstractSocket *socket) con void QHttpNetworkConnectionPrivate::appendUncompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) { - reply.d_func()->responseData.append(fragment); + char *dst = reply.d_func()->responseData.reserve(fragment.size()); + qMemCopy(dst, fragment.constData(), fragment.size()); } void QHttpNetworkConnectionPrivate::appendCompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) @@ -189,6 +192,11 @@ qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailable(const QHttpNetw return reply.d_func()->responseData.size(); } +qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const +{ + return reply.d_func()->responseData.nextDataBlockSize(); +} + qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetworkReply &reply) const { return reply.d_func()->compressedData.size(); @@ -196,15 +204,15 @@ qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetwor qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize) { - QByteArray *ba = &reply.d_func()->responseData; - if (maxSize == -1 || maxSize >= ba->size()) { + QRingBuffer *rb = &reply.d_func()->responseData; + if (maxSize == -1 || maxSize >= rb->size()) { // read the whole data - data = *ba; - ba->clear(); + data = rb->readAll(); + rb->clear(); } else { // read only the requested length - data = ba->mid(0, maxSize); - ba->remove(0, maxSize); + data.resize(maxSize); + rb->read(data.data(), maxSize); } return data.size(); } @@ -591,7 +599,7 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN // try to reconnect/resend before sending an error. if (channels[i].reconnectAttempts-- > 0) { resendCurrentRequest(socket); - } else { + } 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); @@ -643,36 +651,58 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN } break; case QHttpNetworkReplyPrivate::ReadingDataState: { - QBuffer fragment; - fragment.open(QIODevice::WriteOnly); - bytes = reply->d_func()->readBody(socket, &fragment); - if (bytes) { - if (reply->d_func()->autoDecompress) - appendCompressedData(*reply, fragment.data()); - else - appendUncompressedData(*reply, fragment.data()); - - if (!reply->d_func()->autoDecompress) { - reply->d_func()->totalProgress += fragment.size(); - if (shouldEmitSignals(reply)) { - emit reply->readyRead(); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - // emit dataReadProgress signal (signal is currently not connected - // to the rest of QNAM) since readProgress of the - // QNonContiguousByteDevice is used - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - } + 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 (shouldEmitSignals(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; } + } + else + { + // use the traditional slower reading (for compressed encoding, chunked encoding, + // no content-length etc) + QBuffer fragment; + fragment.open(QIODevice::WriteOnly); + bytes = reply->d_func()->readBody(socket, &fragment); + if (bytes) { + if (reply->d_func()->autoDecompress) + appendCompressedData(*reply, fragment.data()); + else + appendUncompressedData(*reply, fragment.data()); + + if (!reply->d_func()->autoDecompress) { + reply->d_func()->totalProgress += fragment.size(); + if (shouldEmitSignals(reply)) { + emit reply->readyRead(); + // make sure that the reply is valid + if (channels[i].reply != reply) + return; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used + 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 - } + else if (!expand(socket, reply, false)) { // expand a chunk if possible + return; // ### expand failed + } #endif + } } if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) break; @@ -887,6 +917,7 @@ void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket, Q_ASSERT(socket); int i = indexOf(socket); + if (channels[i].authMehtod != QAuthenticatorPrivate::None) { if (!(channels[i].authMehtod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 401)) { QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].authenticator); @@ -1361,7 +1392,8 @@ void QHttpNetworkConnectionPrivate::_q_encrypted() QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender()); if (!socket) return; // ### error - channels[indexOf(socket)].state = IdleState; + int i = indexOf(socket); + channels[i].state = IdleState; sendRequest(socket); } diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index bc4d948..a0813d4 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -242,7 +242,8 @@ public: #ifndef QT_NO_OPENSSL bool ignoreSSLErrors; #endif - Channel() :state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), reconnectAttempts(2), + 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) @@ -258,6 +259,7 @@ public: void appendCompressedData(QHttpNetworkReply &reply, const QByteArray &fragment); qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const; + qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const; qint64 compressedBytesAvailable(const QHttpNetworkReply &reply) const; qint64 read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize); diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 47fb6d1..483589b 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -167,6 +167,15 @@ qint64 QHttpNetworkReply::bytesAvailable() const return -1; } +qint64 QHttpNetworkReply::bytesAvailableNextBlock() const +{ + Q_D(const QHttpNetworkReply); + if (d->connection) + return d->connection->d_func()->uncompressedBytesAvailableNextBlock(*this); + else + return -1; +} + QByteArray QHttpNetworkReply::read(qint64 maxSize) { Q_D(QHttpNetworkReply); @@ -176,6 +185,12 @@ QByteArray QHttpNetworkReply::read(qint64 maxSize) return data; } +QByteArray QHttpNetworkReply::readAny() +{ + Q_D(QHttpNetworkReply); + return d->responseData.read(); +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -187,7 +202,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), - autoDecompress(false), requestIsPrepared(false) + autoDecompress(false), responseData(0), requestIsPrepared(false) { } @@ -540,6 +555,30 @@ bool QHttpNetworkReplyPrivate::connectionCloseEnabled() headerField("proxy-connection").toLower().contains("close")); } +// note this function can only be used for non-chunked, non-compressed with +// known content length +qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QRingBuffer *rb) +{ + quint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); + char* dst = rb->reserve(toBeRead); + qint64 haveRead = socket->read(dst, toBeRead); + if (haveRead == -1) { + rb->chop(toBeRead); + return 0; // ### error checking here; + } + + rb->chop(toBeRead - haveRead); + + if (contentRead + haveRead == bodyLength) { + state = AllDoneState; + socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining + } + + contentRead += haveRead; + return haveRead; +} + + qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out) { qint64 bytes = 0; @@ -553,7 +592,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } if (state == AllDoneState) - socket->readAll(); // Read the rest to clean (CRLF) + socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining contentRead += bytes; return bytes; } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 08bd886..b86cfaa 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -79,6 +79,7 @@ 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> QT_BEGIN_NAMESPACE @@ -120,7 +121,9 @@ public: QString reasonPhrase() const; qint64 bytesAvailable() const; + qint64 bytesAvailableNextBlock() const; QByteArray read(qint64 maxSize = -1); + QByteArray readAny(); bool isFinished() const; @@ -158,6 +161,7 @@ public: qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QIODevice *out); + qint64 readBodyFast(QAbstractSocket *socket, QRingBuffer *rb); bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); @@ -193,7 +197,7 @@ public: qint64 bodyLength; qint64 contentRead; qint64 totalProgress; - QByteArray fragment; + QByteArray fragment; // used for header, status, chunk header etc, not for reply data qint64 currentChunkSize; qint64 currentChunkRead; QPointer<QHttpNetworkConnection> connection; @@ -204,7 +208,7 @@ public: #endif bool autoDecompress; - QByteArray responseData; // uncompressed body + QRingBuffer responseData; // uncompressed body QByteArray compressedData; // compressed body (temporary) bool requestIsPrepared; }; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 71808d4..db84e58 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -649,16 +649,14 @@ 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; - - QByteArray data = httpReply->read(bytesToRead); - writeDownstreamData(data); + while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0) { + const QByteArray data = httpReply->readAny(); + writeDownstreamData(data); + } } void QNetworkAccessHttpBackend::replyFinished() diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 265ebe9..de39970 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -56,7 +56,9 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() : backend(0), outgoingData(0), outgoingDataBuffer(0), copyDevice(0), networkCache(0), cacheEnabled(false), cacheSaveDevice(0), + notificationHandlingPaused(false), bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), + httpStatusCode(0), state(Idle) { } @@ -89,7 +91,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() void QNetworkReplyImplPrivate::_q_copyReadyRead() { Q_Q(QNetworkReplyImpl); - if (!copyDevice && !q->isOpen()) + if (!copyDevice || !q->isOpen()) return; forever { @@ -126,9 +128,11 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() lastBytesDownloaded = bytesDownloaded; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); + pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); emit q->readyRead(); + resumeNotificationHandling(); } void QNetworkReplyImplPrivate::_q_copyReadChannelFinished() @@ -262,6 +266,9 @@ void QNetworkReplyImplPrivate::backendNotify(InternalNotifications notification) void QNetworkReplyImplPrivate::handleNotifications() { + if (notificationHandlingPaused) + return; + NotificationQueue current = pendingNotifications; pendingNotifications.clear(); @@ -292,6 +299,22 @@ void QNetworkReplyImplPrivate::handleNotifications() } } +// Do not handle the notifications while we are emitting downloadProgress +// or readyRead +void QNetworkReplyImplPrivate::pauseNotificationHandling() +{ + notificationHandlingPaused = true; +} + +// Resume notification handling +void QNetworkReplyImplPrivate::resumeNotificationHandling() +{ + Q_Q(QNetworkReplyImpl); + notificationHandlingPaused = false; + if (pendingNotifications.size() >= 1) + QCoreApplication::postEvent(q, new QEvent(QEvent::NetworkReplyUpdated)); +} + void QNetworkReplyImplPrivate::createCache() { // check if we can save and if we're allowed to @@ -347,7 +370,9 @@ void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytes { Q_Q(QNetworkReplyImpl); bytesUploaded = bytesSent; + pauseNotificationHandling(); emit q->uploadProgress(bytesSent, bytesTotal); + resumeNotificationHandling(); } @@ -368,8 +393,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) if (!q->isOpen()) return; - char *ptr = readBuffer.reserve(data.size()); - memcpy(ptr, data.constData(), data.size()); + readBuffer.append(data); if (cacheEnabled && !cacheSaveDevice) { // save the meta data @@ -398,12 +422,14 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) QPointer<QNetworkReplyImpl> qq = q; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); + pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); emit q->readyRead(); // hopefully we haven't been deleted here if (!qq.isNull()) { + resumeNotificationHandling(); // do we still have room in the buffer? if (nextDownstreamBlockSize() > 0) backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); @@ -441,6 +467,7 @@ void QNetworkReplyImplPrivate::finished() state = Finished; pendingNotifications.clear(); + pauseNotificationHandling(); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (totalSize.isNull() || totalSize == -1) { emit q->downloadProgress(bytesDownloaded, bytesDownloaded); @@ -448,14 +475,17 @@ void QNetworkReplyImplPrivate::finished() if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer)) emit q->uploadProgress(0, 0); + resumeNotificationHandling(); completeCacheSave(); // note: might not be a good idea, since users could decide to delete us // which would delete the backend too... // maybe we should protect the backend + pauseNotificationHandling(); emit q->readChannelFinished(); emit q->finished(); + resumeNotificationHandling(); } void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const QString &errorMessage) diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 4d75526..3e89a00 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -130,6 +130,9 @@ public: void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); void setNetworkCache(QAbstractNetworkCache *networkCache); + + void pauseNotificationHandling(); + void resumeNotificationHandling(); void backendNotify(InternalNotifications notification); void handleNotifications(); void createCache(); @@ -159,6 +162,8 @@ public: QIODevice *cacheSaveDevice; NotificationQueue pendingNotifications; + bool notificationHandlingPaused; + QUrl urlForLastAuthentication; #ifndef QT_NO_NETWORKPROXY QNetworkProxy lastProxyAuthentication; diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index 0165385..87902c3 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -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"); diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 5fda228..7052bcc2 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -43,8 +43,6 @@ #ifndef QT_NO_NETWORKPROXY -#if defined(UNICODE) - #include <qmutex.h> #include <qstringlist.h> #include <qregexp.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 @@ -401,15 +397,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/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 05ef2e6..1a50dc4 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -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 */ diff --git a/src/network/socket/qlocalserver_tcp.cpp b/src/network/socket/qlocalserver_tcp.cpp index b248f2f..bcf822e 100644 --- a/src/network/socket/qlocalserver_tcp.cpp +++ b/src/network/socket/qlocalserver_tcp.cpp @@ -92,7 +92,7 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut) { if (pendingConnections.isEmpty()) tcpServer.waitForNewConnection(msec, timedOut); - else + else if (timedOut) *timedOut = false; } diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 1cb804a..c2e05cd 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -43,6 +43,7 @@ #include "qlocalserver_p.h" #include "qlocalsocket.h" #include "qlocalsocket_p.h" +#include "qnet_unix_p.h" #ifndef QT_NO_LOCALSERVER @@ -88,7 +89,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(); @@ -107,7 +108,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) fullServerName.toLatin1().size() + 1); // 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 +121,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; @@ -172,7 +173,7 @@ void QLocalServerPrivate::_q_onNewConnection() ::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(); diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 6af5ca5..c4f8f3c 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -62,9 +62,8 @@ bool QLocalServerPrivate::addListener() listeners << Listener(); Listener &listener = listeners.last(); - QT_WA({ - listener.handle = CreateNamedPipeW( - (TCHAR*)fullServerName.utf16(), // 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 @@ -74,19 +73,7 @@ bool QLocalServerPrivate::addListener() BUFSIZE, // input buffer size 3000, // client time-out NULL); - }, { - listener.handle = CreateNamedPipeA( - fullServerName.toLocal8Bit().constData(), // 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); - }); + if (listener.handle == INVALID_HANDLE_VALUE) { setError(QLatin1String("QLocalServerPrivate::addListener")); listeners.removeLast(); diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 24b5dd6..bdbba42 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -74,43 +74,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 { diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 41dac3c..d038794 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -41,6 +41,7 @@ #include "qlocalsocket.h" #include "qlocalsocket_p.h" +#include "qnet_unix_p.h" #ifndef QT_NO_LOCALSOCKET @@ -232,7 +233,7 @@ 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; @@ -282,7 +283,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) { diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 2b8d7e5..b1b69fc 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -137,25 +137,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 +154,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) { diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index b130a9b..0c1fa19 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -42,6 +42,7 @@ //#define QNATIVESOCKETENGINE_DEBUG #include "qnativesocketengine_p.h" +#include "private/qnet_unix_p.h" #include "qiodevice.h" #include "qhostaddress.h" #include "qvarlengtharray.h" @@ -161,7 +162,7 @@ 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); + int socket = qt_safe_socket(protocol, type, 0); if (socket <= 0) { switch (errno) { @@ -466,7 +467,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 bool QNativeSocketEnginePrivate::nativeListen(int backlog) { - if (qt_socket_listen(socketDescriptor, backlog) < 0) { + if (qt_safe_listen(socketDescriptor, backlog) < 0) { switch (errno) { case EADDRINUSE: setError(QAbstractSocket::AddressInUseError, @@ -493,7 +494,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog) int QNativeSocketEnginePrivate::nativeAccept() { - int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0); + int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor); #endif @@ -833,33 +834,11 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - QTime timer; - timer.start(); - 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 (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; - } - - tv.tv_sec = t / 1000; - tv.tv_usec = (t % 1000) * 1000; - } - } while (true); - + if (selectForRead) + retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); + else + retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); return retval; } @@ -880,28 +859,8 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - QTime timer; - timer.start(); - int ret; - do { - ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); - if (ret != -1 || errno != EINTR) - break; - - if (timeout > 0) { - // recalculate the timeout - int t = timeout - timer.elapsed(); - if (t < 0) { - // oops, timeout turned negative? - ret = -1; - break; - } - - tv.tv_sec = t / 1000; - tv.tv_usec = (t % 1000) * 1000; - } - } while (true); + ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); if (ret <= 0) return ret; diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 59a3b60..ce8d810 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -918,15 +918,9 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, (struct sockaddr *) &aa, &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); } @@ -955,36 +949,32 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l 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..ffd5b39 --- /dev/null +++ b/src/network/socket/qnet_unix_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@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> + +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; +#ifdef SOCK_CLOEXEC + 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; + EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, 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 + +QT_END_NAMESPACE + +#endif // QNET_UNIX_P_H diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index b1fe64a..17e49d2 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 \ |