diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 32 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnection_p.h | 4 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 1 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkrequest.cpp | 22 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkrequest_p.h | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl.cpp | 3 | ||||
-rw-r--r-- | src/network/bearer/qnetworkconfiguration.cpp | 115 | ||||
-rw-r--r-- | src/network/bearer/qnetworkconfiguration.h | 4 |
8 files changed, 174 insertions, 11 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 5c3c38606d..c3e3716b26 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -85,6 +85,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif + , preConnectRequests(0) { channels = new QHttpNetworkConnectionChannel[channelCount]; } @@ -96,6 +97,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCoun #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif + , preConnectRequests(0) { channels = new QHttpNetworkConnectionChannel[channelCount]; } @@ -541,6 +543,9 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor reply->d_func()->connectionChannel = &channels[0]; // will have the correct one set later HttpMessagePair pair = qMakePair(request, reply); + if (request.isPreConnect()) + preConnectRequests++; + switch (request.priority()) { case QHttpNetworkRequest::HighPriority: highPriorityQueue.prepend(pair); @@ -925,15 +930,24 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() // If there is not already any connected channels we need to connect a new one. // We do not pair the channel with the request until we know if it is // connected or not. This is to reuse connected channels before we connect new once. - int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count(); - for (int i = 0; i < channelCount; ++i) { + int queuedRequests = highPriorityQueue.count() + lowPriorityQueue.count(); + + // in case we have in-flight preconnect requests and normal requests, + // we only need one socket for each (preconnect, normal request) pair + int neededOpenChannels = queuedRequests; + if (preConnectRequests > 0) { + int normalRequests = queuedRequests - preConnectRequests; + neededOpenChannels = qMax(normalRequests, preConnectRequests); + } + for (int i = 0; i < channelCount && neededOpenChannels > 0; ++i) { bool connectChannel = false; if (channels[i].socket) { if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState) || channels[i].pendingEncrypt) // pendingEncrypt == "EncryptingState" - queuedRequest--; - if ( queuedRequest <=0 ) + neededOpenChannels--; + + if (neededOpenChannels <= 0) break; if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) connectChannel = true; @@ -947,11 +961,8 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() else if (networkLayerState == IPv6) channels[i].networkLayerPreference = QAbstractSocket::IPv6Protocol; channels[i].ensureConnection(); - queuedRequest--; + neededOpenChannels--; } - - if ( queuedRequest <=0 ) - break; } } @@ -1272,6 +1283,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int #endif //QT_NO_SSL +void QHttpNetworkConnection::preConnectFinished() +{ + d_func()->preConnectRequests--; +} + #ifndef QT_NO_NETWORKPROXY // only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not // from QHttpNetworkConnectionChannel::handleAuthenticationChallenge diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 956499ddab..c54250f6ed 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -131,6 +131,8 @@ public: void setSslContext(QSharedPointer<QSslContext> context); #endif + void preConnectFinished(); + private: Q_DECLARE_PRIVATE(QHttpNetworkConnection) Q_DISABLE_COPY(QHttpNetworkConnection) @@ -239,6 +241,8 @@ public: QList<HttpMessagePair> highPriorityQueue; QList<HttpMessagePair> lowPriorityQueue; + int preConnectRequests; + #ifndef QT_NO_SSL QSharedPointer<QSslContext> sslContext; #endif diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index a756f22937..1c7a61dca6 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -214,6 +214,7 @@ bool QHttpNetworkConnectionChannel::sendRequest() state = QHttpNetworkConnectionChannel::IdleState; reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); + connection->preConnectFinished(); // will only decrease the counter reply = 0; // so we can reuse this channel return true; // we have a working connection and are done } diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index e5b2eced99..d9f9b555d7 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -49,7 +49,8 @@ QT_BEGIN_NAMESPACE QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, QHttpNetworkRequest::Priority pri, const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0), - autoDecompress(false), pipeliningAllowed(false), withCredentials(true) + autoDecompress(false), pipeliningAllowed(false), withCredentials(true), + preConnect(false) { } @@ -64,6 +65,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest customVerb = other.customVerb; withCredentials = other.withCredentials; ssl = other.ssl; + preConnect = other.preConnect; } QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() @@ -74,8 +76,15 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) + && (priority == other.priority) + && (uploadByteDevice == other.uploadByteDevice) + && (autoDecompress == other.autoDecompress) + && (pipeliningAllowed == other.pipeliningAllowed) + // we do not clear the customVerb in setOperation + && (operation != QHttpNetworkRequest::Custom || (customVerb == other.customVerb)) + && (withCredentials == other.withCredentials) && (ssl == other.ssl) - && (uploadByteDevice == other.uploadByteDevice); + && (preConnect == other.preConnect); } QByteArray QHttpNetworkRequestPrivate::methodName() const @@ -205,6 +214,15 @@ void QHttpNetworkRequest::setSsl(bool s) d->ssl = s; } +bool QHttpNetworkRequest::isPreConnect() const +{ + return d->preConnect; +} +void QHttpNetworkRequest::setPreConnect(bool preConnect) +{ + d->preConnect = preConnect; +} + qint64 QHttpNetworkRequest::contentLength() const { return d->contentLength(); diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index fc4a6928c6..ce9fbb1509 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -120,6 +120,9 @@ public: bool isSsl() const; void setSsl(bool); + bool isPreConnect() const; + void setPreConnect(bool preConnect); + void setUploadByteDevice(QNonContiguousByteDevice *bd); QNonContiguousByteDevice* uploadByteDevice() const; @@ -151,6 +154,7 @@ public: bool pipeliningAllowed; bool withCredentials; bool ssl; + bool preConnect; }; diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 8205d81191..ddef970966 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -635,6 +635,9 @@ void QNetworkReplyHttpImplPrivate::postRequest() q->setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl); httpRequest.setSsl(ssl); + bool preConnect = (scheme == QLatin1String("preconnect-http") + || scheme == QLatin1String("preconnect-https")); + httpRequest.setPreConnect(preConnect); #ifndef QT_NO_NETWORKPROXY QNetworkProxy transparentProxy, cacheProxy; diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp index 615ef21661..52fbb2441f 100644 --- a/src/network/bearer/qnetworkconfiguration.cpp +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -42,6 +42,12 @@ #include "qnetworkconfiguration.h" #include "qnetworkconfiguration_p.h" +#ifdef Q_OS_BLACKBERRY +#include "private/qcore_unix_p.h" // qt_safe_open +#include <QDebug> +#include <sys/pps.h> +#endif // Q_OS_BLACKBERRY + QT_BEGIN_NAMESPACE /*! @@ -198,8 +204,81 @@ QT_BEGIN_NAMESPACE \value BearerHSPA The configuration is for High Speed Packet Access (HSPA) interface. \value BearerBluetooth The configuration is for a Bluetooth interface. \value BearerWiMAX The configuration is for a WiMAX interface. + \value BearerEVDO The configuration is for an EVDO (3G) interface. + \value BearerLTE The configuration is for a LTE (4G) interface. */ +#ifdef Q_OS_BLACKBERRY +static const char cellularStatusFile[] = "/pps/services/radioctrl/modem0/status_public"; + +static QNetworkConfiguration::BearerType cellularStatus() +{ + QNetworkConfiguration::BearerType ret = QNetworkConfiguration::BearerUnknown; + + int cellularStatusFD; + if ((cellularStatusFD = qt_safe_open(cellularStatusFile, O_RDONLY)) == -1) { + qWarning() << Q_FUNC_INFO << "failed to open" << cellularStatusFile; + return ret; + } + char buf[2048]; + if (qt_safe_read(cellularStatusFD, &buf, sizeof(buf)) == -1) { + qWarning() << Q_FUNC_INFO << "read from PPS file failed:" << strerror(errno); + qt_safe_close(cellularStatusFD); + return ret; + } + pps_decoder_t ppsDecoder; + if (pps_decoder_initialize(&ppsDecoder, buf) != PPS_DECODER_OK) { + qWarning() << Q_FUNC_INFO << "failed to initialize PPS decoder"; + qt_safe_close(cellularStatusFD); + return ret; + } + pps_decoder_error_t err; + if ((err = pps_decoder_push(&ppsDecoder, 0)) != PPS_DECODER_OK) { + qWarning() << Q_FUNC_INFO << "pps_decoder_push failed" << err; + pps_decoder_cleanup(&ppsDecoder); + qt_safe_close(cellularStatusFD); + return ret; + } + if (!pps_decoder_is_integer(&ppsDecoder, "network_technology")) { + qWarning() << Q_FUNC_INFO << "field has not the expected data type"; + pps_decoder_cleanup(&ppsDecoder); + qt_safe_close(cellularStatusFD); + return ret; + } + int type; + if (!pps_decoder_get_int(&ppsDecoder, "network_technology", &type) + == PPS_DECODER_OK) { + qWarning() << Q_FUNC_INFO << "could not read bearer type from PPS"; + pps_decoder_cleanup(&ppsDecoder); + qt_safe_close(cellularStatusFD); + return ret; + } + switch (type) { + case 0: // 0 == NONE + break; // unhandled + case 1: // fallthrough, 1 == GSM + case 4: // 4 == CDMA_1X + ret = QNetworkConfiguration::Bearer2G; + break; + case 2: // 2 == UMTS + ret = QNetworkConfiguration::BearerWCDMA; + break; + case 8: // 8 == EVDO + ret = QNetworkConfiguration::BearerEVDO; + break; + case 16: // 16 == LTE + ret = QNetworkConfiguration::BearerLTE; + break; + default: + qWarning() << Q_FUNC_INFO << "unhandled bearer type" << type; + break; + } + pps_decoder_cleanup(&ppsDecoder); + qt_safe_close(cellularStatusFD); + return ret; +} +#endif // Q_OS_BLACKBERRY + /*! Constructs an invalid configuration object. @@ -420,6 +499,18 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const QMutexLocker locker(&d->mutex); +#ifdef Q_OS_BLACKBERRY + // for cellular configurations, we need to determine the exact + // type right now, because it might have changed after the last scan + if (d->bearerType == QNetworkConfiguration::Bearer2G) { + QNetworkConfiguration::BearerType type = cellularStatus(); + // if reading the status failed for some reason, just + // fall back to 2G + return (type == QNetworkConfiguration::BearerUnknown) + ? QNetworkConfiguration::Bearer2G : type; + } +#endif // Q_OS_BLACKBERRY + return d->bearerType; } @@ -464,6 +555,12 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const \row \li BearerWiMAX \li WiMAX + \row + \li BearerEVDO + \li EVDO + \row + \li BearerLTE + \li LTE \endtable This function returns an empty string if this is an invalid configuration, a network @@ -489,6 +586,20 @@ QString QNetworkConfiguration::bearerTypeName() const case BearerWLAN: return QStringLiteral("WLAN"); case Bearer2G: +#ifdef Q_OS_BLACKBERRY + { + // for cellular configurations, we need to determine the exact + // type right now, because it might have changed after the last scan + QNetworkConfiguration::BearerType type = cellularStatus(); + if (type == QNetworkConfiguration::BearerWCDMA) { + return QStringLiteral("WCDMA"); + } else if (type == QNetworkConfiguration::BearerEVDO) { + return QStringLiteral("EVDO"); + }else if (type == QNetworkConfiguration::BearerLTE) { + return QStringLiteral("LTE"); + } + } +#endif // Q_OS_BLACKBERRY return QStringLiteral("2G"); case BearerCDMA2000: return QStringLiteral("CDMA2000"); @@ -500,6 +611,10 @@ QString QNetworkConfiguration::bearerTypeName() const return QStringLiteral("Bluetooth"); case BearerWiMAX: return QStringLiteral("WiMAX"); + case BearerEVDO: + return QStringLiteral("EVDO"); + case BearerLTE: + return QStringLiteral("LTE"); case BearerUnknown: break; } diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h index 25dafcb282..8809e5526a 100644 --- a/src/network/bearer/qnetworkconfiguration.h +++ b/src/network/bearer/qnetworkconfiguration.h @@ -97,7 +97,9 @@ public: BearerWCDMA, BearerHSPA, BearerBluetooth, - BearerWiMAX + BearerWiMAX, + BearerEVDO, + BearerLTE }; StateFlags state() const; |