5#include <private/qabstractsocket_p.h>
7#include "private/qnoncontiguousbytedevice_p.h"
8#include <private/qnetworkrequest_p.h>
9#include <private/qobject_p.h>
10#include <private/qauthenticator_p.h>
11#include "private/qhostinfo_p.h"
15#include <private/qdecompresshelper_p.h>
16#include <private/qsocketabstraction_p.h>
25# include <private/qsslsocket_p.h>
26# include <QtNetwork/qsslkey.h>
27# include <QtNetwork/qsslcipher.h>
28# include <QtNetwork/qsslconfiguration.h>
29# include <QtNetwork/qsslerror.h>
59 isLocalSocket(isLocalSocket),
61 channelCount(connectionCount),
63#ifndef QT_NO_NETWORKPROXY
108 if (
auto *absSocket = qobject_cast<QAbstractSocket *>(
channels[
i].
socket)) {
118 qDebug() <<
"Should pause socket but there is no way to do it for local sockets";
129 if (
auto *absSocket = qobject_cast<QAbstractSocket *>(
channels[
i].
socket)) {
142 qDebug() <<
"Should resume socket but there is no way to do it for local sockets";
157 qFatal(
"Called with unknown socket object.");
169 bool emitError =
true;
171 int otherSocket = (
i == 0 ? 1 : 0);
206 qWarning(
"We got a connection error when networkLayerState is Unknown");
215 return reply.d_func()->responseData.byteAmount();
220 return reply.d_func()->responseData.sizeNextBlock();
244 if (uploadByteDevice) {
246 const qint64 uploadDeviceSize = uploadByteDevice->
size();
247 if (contentLength != -1 && uploadDeviceSize != -1) {
249 if (uploadDeviceSize < contentLength)
250 request.setContentLength(uploadDeviceSize);
251 }
else if (contentLength == -1 && uploadDeviceSize != -1) {
253 request.setContentLength(uploadDeviceSize);
254 }
else if (contentLength != -1 && uploadDeviceSize == -1) {
256 }
else if (
Q_UNLIKELY(contentLength == -1 && uploadDeviceSize == -1)) {
257 qFatal(
"QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given");
262#ifndef QT_NO_NETWORKPROXY
266 request.setHeaderField(
"Proxy-Connection",
"Keep-Alive");
271 request.setHeaderField(
"Connection",
"Keep-Alive");
272#ifndef QT_NO_NETWORKPROXY
282 if (
value.isEmpty()) {
283#ifndef QT_NO_COMPRESS
285 request.setHeaderField(
"Accept-Encoding", acceptedEncoding);
286 request.d->autoDecompress =
true;
289 request.d->autoDecompress =
false;
304 request.setHeaderField(
"User-Agent",
"Mozilla/5.0");
312 }
else if (
value.isEmpty()) {
317 host = (u
'[' +
hostName + u
']').toLatin1();
331 request.prependHeaderField(
"Host", host);
334 reply->d_func()->requestIsPrepared =
true;
355 reply->d_func()->eraseData();
377 if (fromChannel >= 0) {
389 if (
i == fromChannel)
396 if (otherAuth->user().compare(auth->user()))
397 otherAuth->
setUser(auth->user());
398 if (otherAuth->password().compare(auth->password()))
399 otherAuth->setPassword(auth->password());
406 bool isProxy,
bool &resend)
416 const QByteArray header = isProxy ?
"proxy-authenticate" :
"www-authenticate";
418 const bool isSupported = std::any_of(authenticationMethods.begin(), authenticationMethods.end(),
443 if (
channels[
i].authenticationCredentialsSent) {
446 priv->hasFailed =
true;
451#ifndef QT_NO_NETWORKPROXY
456 priv->hasFailed =
true;
515 return std::move(
result.redirectUrl);
545 if (targetUrlScheme ==
"http"_L1 || targetUrlScheme ==
"https"_L1
546 || targetUrlScheme.startsWith(
"unix"_L1)) {
556 if (priorUrl.host() != redirectUrl.
host()
557 || priorUrl.scheme() != targetUrlScheme
558 || priorUrl.port() != redirectUrl.
port()) {
565 Q_ASSERT(!
"Unexpected redirect policy");
585 const bool authNeeded =
channel.lastStatus == 401;
586 const bool ntlmNegoOk = ntlmNego && authNeeded
588 || !
channel.authenticationCredentialsSent);
590 !ntlmNego && (authNeeded ||
request.headerField(
"Authorization").isEmpty());
591 if (ntlmNegoOk || otherOk) {
594 request.setHeaderField(
"Authorization", response);
595 channel.authenticationCredentialsSent =
true;
599#if QT_CONFIG(networkproxy)
600 authenticator = &
channel.proxyAuthenticator;
606 const bool proxyAuthNeeded =
channel.lastStatus == 407;
607 const bool ntlmNegoOk = ntlmNego && proxyAuthNeeded
609 const bool otherOk = !ntlmNego;
610 if (ntlmNegoOk || otherOk) {
613 request.setHeaderField(
"Proxy-Authorization", response);
614 channel.proxyCredentialsSent =
true;
627 reply->d_func()->connection =
q;
647 if (!pair.second->d_func()->requestIsPrepared)
675 if (!pair.second->d_func()->requestIsPrepared)
683 if (!pair.second->d_func()->requestIsPrepared)
718 if (!messagePair.second->d_func()->requestIsPrepared)
727 if (!messagePair.second->d_func()->requestIsPrepared)
804 if (!
channels[
i].proxyAuthenticator.isNull()
824 if (lengthBefore ==
channels[
i].alreadyPipelinedRequests.size())
837 if (lengthBefore ==
channels[
i].alreadyPipelinedRequests.size())
851 for (
int i =
queue.size() - 1;
i >= 0; --
i) {
863 if (!
request.isPipeliningAllowed())
872 if (!messagePair.second->d_func()->requestIsPrepared)
874 channel.pipelineInto(messagePair);
928 errorString = extraDetail;
960 if (
reply->isAborted()) {
992 return pair.second ==
reply;
996 auto it = std::find_if(seq.cbegin(),
end, foundReply);
1007 if (messagePair.second ==
reply) {
1018 if (messagePair.second ==
reply) {
1095 if (
channels[0].h2RequestsToSend.size()) {
1135 int neededOpenChannels = queuedRequests;
1141 if (neededOpenChannels <= 0)
1144 QVarLengthArray<int> channelsToConnect;
1147 for (
int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++
i) {
1155 neededOpenChannels--;
1161 channelsToConnect.push_back(
i);
1162 neededOpenChannels--;
1167 for (
int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++
i) {
1171 channelsToConnect.push_back(
i);
1172 neededOpenChannels--;
1175 auto channelToConnectSpan =
QSpan{channelsToConnect};
1176 while (!channelToConnectSpan.isEmpty()) {
1177 const int channel = channelToConnectSpan.front();
1178 channelToConnectSpan = channelToConnectSpan.sliced(1);
1213#ifndef QT_NO_NETWORKPROXY
1234 bool immediateResultValid =
false;
1238 &immediateResultValid,
1240 if (immediateResultValid) {
1251 bool foundAddress =
false;
1259 if (!foundAddress) {
1260 foundAddress =
true;
1265 if (!foundAddress) {
1266 foundAddress =
true;
1283#ifndef QT_NO_NETWORKPROXY
1304 qDebug(
"QHttpNetworkConnectionPrivate::_q_hostLookupFinished"
1305 " could not de-queue request, failed to report HostNotFoundError");
1362 connectionType)), parent)
1397 d->fillHttp2Queue();
1408 return d_func()->channels;
1411#ifndef QT_NO_NETWORKPROXY
1415 d->networkProxy = networkProxy;
1417 if (!
d->networkProxy.user().isEmpty()) {
1418 for (
int i = 0;
i <
d->channelCount; ++
i) {
1419 d->channels[
i].proxyAuthenticator.
setUser(
d->networkProxy.user());
1420 d->channels[
i].proxyAuthenticator.setPassword(
d->networkProxy.password());
1428 return d->networkProxy;
1434 for (
int i = 0;
i <
d->channelCount; ++
i)
1435 d->channels[
i].setProxy(networkProxy);
1441 return d->channels[0].proxy;
1448 return d->connectionType;
1454 d->connectionType =
type;
1460 return d->http2Parameters;
1478 for (
int i = 0;
i <
d->activeChannelCount; ++
i)
1479 d->channels[
i].setSslConfiguration(
config);
1485 return d->sslContext;
1491 d->sslContext = std::move(context);
1503 for (
int i = 0;
i <
d->channelCount; ++
i) {
1504 d->channels[
i].ignoreSslErrors();
1508 d->channels[
channel].ignoreSslErrors();
1521 for (
int i = 0;
i <
d->channelCount; ++
i) {
1522 d->channels[
i].ignoreSslErrors(errors);
1526 d->channels[
channel].ignoreSslErrors(errors);
1534 d_func()->preConnectRequests--;
1540 return d->peerVerifyName;
1546 d->peerVerifyName = peerName;
1559 for (
int i = 0;
i <
d->activeChannelCount;
i++) {
1566 d->connectionMonitor.stopMonitoring();
1569#ifndef QT_NO_NETWORKPROXY
1580 && (chan->switchedToHttp2 || chan->h2RequestsToSend.size() > 0))
1585 Q_ASSERT(chan->h2RequestsToSend.size() > 0);
1586 reply = chan->h2RequestsToSend.cbegin().value().second;
1588 reply = chan->reply;
1602#include "moc_qhttpnetworkconnection_p.cpp"
IOBluetoothL2CAPChannel * channel
static void pauseSocketNotifiers(QAbstractSocket *)
static void resumeSocketNotifiers(QAbstractSocket *)
SocketState
This enum describes the different states in which a socket can be.
static constexpr auto IPv4Protocol
static constexpr auto AnyIPProtocol
static constexpr auto IPv6Protocol
static bool isMethodSupported(QByteArrayView method)
static QAuthenticatorPrivate * getPrivate(QAuthenticator &auth)
The QAuthenticator class provides an authentication object.
QString user() const
Returns the user used for authentication.
QString password() const
Returns the password used for authentication.
void setUser(const QString &user)
Sets the user used for authentication.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
static QByteArrayList acceptedEncoding()
The QHostAddress class provides an IP address.
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
The QHostInfo class provides static functions for host name lookups.
QList< QHostAddress > addresses() const
Returns the list of IP addresses associated with hostName().
The QHttp2Configuration class controls HTTP/2 parameters and settings.
std::unique_ptr< QAbstractProtocolHandler > protocolHandler
QAuthenticator proxyAuthenticator
void requeueCurrentlyPipelinedRequests()
QAbstractSocket::NetworkLayerProtocol networkLayerPreference
bool proxyCredentialsSent
QHttpNetworkReply * reply
QHttpNetworkRequest request
QMultiMap< int, HttpMessagePair > h2RequestsToSend
void setConnection(QHttpNetworkConnection *c)
@ PipeliningProbablySupported
bool authenticationCredentialsSent
QList< HttpMessagePair > alreadyPipelinedRequests
QAuthenticator authenticator
QString errorDetail(QNetworkReply::NetworkError errorCode, QIODevice *socket, const QString &extraDetail=QString())
QHttpNetworkConnection::ConnectionType connectionType
qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const
void startNetworkLayerStateLookup()
bool shouldEmitChannelError(QIODevice *socket)
void createAuthorization(QIODevice *socket, QHttpNetworkRequest &request)
void emitReplyError(QIODevice *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode)
void fillPipeline(QIODevice *socket)
QHttpNetworkRequest predictNextRequest() const
void prepareRequest(HttpMessagePair &request)
void startHostInfoLookup()
QHttpNetworkConnectionPrivate(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, bool isLocalSocket, QHttpNetworkConnection::ConnectionType type)
void emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator *auth)
NetworkLayerPreferenceState networkLayerState
void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy)
void _q_connectDelayedChannel()
static const int defaultRePipelineLength
void networkLayerDetected(QAbstractSocket::NetworkLayerProtocol protocol)
void _q_startNextRequest()
void requeueRequest(const HttpMessagePair &pair)
QList< HttpMessagePair > lowPriorityQueue
void removeReply(QHttpNetworkReply *reply)
void _q_hostLookupFinished(const QHostInfo &info)
QHttpNetworkReply * predictNextRequestsReply() const
QList< HttpMessagePair > highPriorityQueue
void updateChannel(int i, const HttpMessagePair &messagePair)
bool handleAuthenticateChallenge(QIODevice *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend)
QHttpNetworkReply * queueRequest(const QHttpNetworkRequest &request)
QHttpNetworkConnectionChannel *const channels
void readMoreLater(QHttpNetworkReply *reply)
bool dequeueRequest(QIODevice *socket)
QTimer delayedConnectionTimer
QNetworkProxy networkProxy
int indexOf(QIODevice *socket) const
~QHttpNetworkConnectionPrivate()
qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const
static const int defaultPipelineLength
static ParseRedirectResult parseRedirectResponse(QHttpNetworkReply *reply)
void preConnectFinished()
QHttpNetworkReply * sendRequest(const QHttpNetworkRequest &request)
void onlineStateChanged(bool isOnline)
QHttp2Configuration http2Parameters() const
void setCacheProxy(const QNetworkProxy &networkProxy)
QNetworkProxy cacheProxy() const
QHttpNetworkConnectionChannel * channels() const
void setPeerVerifyName(const QString &peerName)
void setConnectionType(ConnectionType type)
QString peerVerifyName() const
QNetworkProxy transparentProxy() const
~QHttpNetworkConnection()
ConnectionType connectionType() const
@ ConnectionTypeHTTP2Direct
void setSslContext(std::shared_ptr< QSslContext > context)
std::shared_ptr< QSslContext > sslContext() const
void setTransparentProxy(const QNetworkProxy &networkProxy)
void setHttp2Parameters(const QHttp2Configuration ¶ms)
void ignoreSslErrors(int channel=-1)
void setSslConfiguration(const QSslConfiguration &config)
QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port=80, bool encrypt=false, bool isLocalSocket=false, QObject *parent=nullptr, ConnectionType connectionType=ConnectionTypeHTTP)
\inmodule QtCore \reentrant
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
QString errorString() const
Returns a human-readable description of the last device error that occurred.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void removeAt(qsizetype i)
const_reference at(qsizetype i) const noexcept
void prepend(rvalue_ref t)
static QLocale system()
Returns a QLocale object initialized to the system locale.
iterator insert(const Key &key, const T &value)
const_iterator cend() const
void reachabilityChanged(bool isOnline)
The QNetworkProxy class provides a network layer proxy.
void setUser(const QString &userName)
Sets the user name for proxy authentication to be user.
Capabilities capabilities() const
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
QString hostName() const
Returns the host name of the proxy host.
@ HostNameLookupCapability
QVariant header(QNetworkRequest::KnownHeaders header) const
Returns the value of the known header header, if that header was sent by the remote server.
void setRequest(const QNetworkRequest &request)
Sets the associated request for this object to be request.
NetworkError
Indicates all possible error conditions found during the processing of the request.
@ TemporaryNetworkFailureError
@ SslHandshakeFailedError
@ ProxyAuthenticationRequiredError
@ AuthenticationRequiredError
QNetworkRequest request() const
Returns the request that was posted for this reply.
QUrl url() const
Returns the URL of the content downloaded or uploaded.
Priority priority() const
@ SameOriginRedirectPolicy
@ UserVerifiedRedirectPolicy
@ NoLessSafeRedirectPolicy
QUrl url() const
Returns the URL this network request is referring to.
virtual qint64 size() const =0
Returns the size of the complete device or -1 if unknown.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
The QSslConfiguration class holds the configuration and state of an SSL connection.
static void resumeSocketNotifiers(QSslSocket *)
static void pauseSocketNotifiers(QSslSocket *)
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QByteArray toLatin1() const &
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QByteArray toLocal8Bit() const &
void setSingleShot(bool singleShot)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
void stop()
Stops the timer.
QString userInfo(ComponentFormattingOptions options=PrettyDecoded) const
Returns the user info of the URL, or an empty string if the user info is undefined.
static QByteArray toAce(const QString &domain, AceProcessingOptions options={})
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
QString host(ComponentFormattingOptions=FullyDecoded) const
Returns the host of the URL if it is defined; otherwise an empty string is returned.
QString scheme() const
Returns the scheme of the URL.
int port(int defaultPort=-1) const
static QUrl fromEncoded(QByteArrayView input, ParsingMode mode=TolerantMode)
Parses input and returns the corresponding QUrl.
QSet< QString >::iterator it
QString socketPeerName(QIODevice *device)
QAbstractSocket::SocketState socketState(QIODevice *device)
Combined button and popup list for selecting options.
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id)
static QByteArray makeAcceptLanguage()
static int getPreferredActiveChannelCount(QHttpNetworkConnection::ConnectionType type, int defaultValue)
QPair< QHttpNetworkRequest, QHttpNetworkReply * > HttpMessagePair
static const QSystemLocale * systemLocale()
constexpr const T & qMax(const T &a, const T &b)
GLbitfield GLuint64 timeout
[4]
GLfloat GLfloat GLfloat GLfloat h
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QNetworkRequest request(url)