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");
307 if (
value.isEmpty()) {
312 host = (u
'[' +
hostName + u
']').toLatin1();
326 request.prependHeaderField(
"Host", host);
329 reply->d_func()->requestIsPrepared =
true;
350 reply->d_func()->eraseData();
372 if (fromChannel >= 0) {
384 if (
i == fromChannel)
391 if (otherAuth->user().compare(auth->user()))
392 otherAuth->
setUser(auth->user());
393 if (otherAuth->password().compare(auth->password()))
394 otherAuth->setPassword(auth->password());
401 bool isProxy,
bool &resend)
411 const QByteArray header = isProxy ?
"proxy-authenticate" :
"www-authenticate";
413 const bool isSupported = std::any_of(authenticationMethods.begin(), authenticationMethods.end(),
438 if (
channels[
i].authenticationCredentialsSent) {
441 priv->hasFailed =
true;
446#ifndef QT_NO_NETWORKPROXY
451 priv->hasFailed =
true;
510 return std::move(
result.redirectUrl);
540 if (targetUrlScheme ==
"http"_L1 || targetUrlScheme ==
"https"_L1
541 || targetUrlScheme.startsWith(
"unix"_L1)) {
551 if (priorUrl.host() != redirectUrl.
host()
552 || priorUrl.scheme() != targetUrlScheme
553 || priorUrl.port() != redirectUrl.
port()) {
560 Q_ASSERT(!
"Unexpected redirect policy");
580 const bool authNeeded =
channel.lastStatus == 401;
581 const bool ntlmNegoOk = ntlmNego && authNeeded
583 || !
channel.authenticationCredentialsSent);
585 !ntlmNego && (authNeeded ||
request.headerField(
"Authorization").isEmpty());
586 if (ntlmNegoOk || otherOk) {
589 request.setHeaderField(
"Authorization", response);
590 channel.authenticationCredentialsSent =
true;
594#if QT_CONFIG(networkproxy)
595 authenticator = &
channel.proxyAuthenticator;
601 const bool proxyAuthNeeded =
channel.lastStatus == 407;
602 const bool ntlmNegoOk = ntlmNego && proxyAuthNeeded
604 const bool otherOk = !ntlmNego;
605 if (ntlmNegoOk || otherOk) {
608 request.setHeaderField(
"Proxy-Authorization", response);
609 channel.proxyCredentialsSent =
true;
622 reply->d_func()->connection =
q;
642 if (!pair.second->d_func()->requestIsPrepared)
670 if (!pair.second->d_func()->requestIsPrepared)
678 if (!pair.second->d_func()->requestIsPrepared)
713 if (!messagePair.second->d_func()->requestIsPrepared)
722 if (!messagePair.second->d_func()->requestIsPrepared)
799 if (!
channels[
i].proxyAuthenticator.isNull()
819 if (lengthBefore ==
channels[
i].alreadyPipelinedRequests.size())
832 if (lengthBefore ==
channels[
i].alreadyPipelinedRequests.size())
846 for (
int i =
queue.size() - 1;
i >= 0; --
i) {
858 if (!
request.isPipeliningAllowed())
867 if (!messagePair.second->d_func()->requestIsPrepared)
869 channel.pipelineInto(messagePair);
923 errorString = extraDetail;
955 if (
reply->isAborted()) {
987 return pair.second ==
reply;
991 auto it = std::find_if(seq.cbegin(),
end, foundReply);
1002 if (messagePair.second ==
reply) {
1013 if (messagePair.second ==
reply) {
1090 if (
channels[0].h2RequestsToSend.size()) {
1130 int neededOpenChannels = queuedRequests;
1136 if (neededOpenChannels <= 0)
1139 QVarLengthArray<int> channelsToConnect;
1142 for (
int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++
i) {
1150 neededOpenChannels--;
1156 channelsToConnect.push_back(
i);
1157 neededOpenChannels--;
1162 for (
int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++
i) {
1166 channelsToConnect.push_back(
i);
1167 neededOpenChannels--;
1170 auto channelToConnectSpan =
QSpan{channelsToConnect};
1171 while (!channelToConnectSpan.isEmpty()) {
1172 const int channel = channelToConnectSpan.front();
1173 channelToConnectSpan = channelToConnectSpan.sliced(1);
1208#ifndef QT_NO_NETWORKPROXY
1229 bool immediateResultValid =
false;
1233 &immediateResultValid,
1235 if (immediateResultValid) {
1246 bool foundAddress =
false;
1254 if (!foundAddress) {
1255 foundAddress =
true;
1260 if (!foundAddress) {
1261 foundAddress =
true;
1278#ifndef QT_NO_NETWORKPROXY
1299 qDebug(
"QHttpNetworkConnectionPrivate::_q_hostLookupFinished"
1300 " could not de-queue request, failed to report HostNotFoundError");
1357 connectionType)), parent)
1392 d->fillHttp2Queue();
1403 return d_func()->channels;
1406#ifndef QT_NO_NETWORKPROXY
1410 d->networkProxy = networkProxy;
1412 if (!
d->networkProxy.user().isEmpty()) {
1413 for (
int i = 0;
i <
d->channelCount; ++
i) {
1414 d->channels[
i].proxyAuthenticator.
setUser(
d->networkProxy.user());
1415 d->channels[
i].proxyAuthenticator.setPassword(
d->networkProxy.password());
1423 return d->networkProxy;
1429 for (
int i = 0;
i <
d->channelCount; ++
i)
1430 d->channels[
i].setProxy(networkProxy);
1436 return d->channels[0].proxy;
1443 return d->connectionType;
1449 d->connectionType =
type;
1455 return d->http2Parameters;
1473 for (
int i = 0;
i <
d->activeChannelCount; ++
i)
1474 d->channels[
i].setSslConfiguration(
config);
1480 return d->sslContext;
1486 d->sslContext = std::move(
context);
1498 for (
int i = 0;
i <
d->channelCount; ++
i) {
1499 d->channels[
i].ignoreSslErrors();
1503 d->channels[
channel].ignoreSslErrors();
1516 for (
int i = 0;
i <
d->channelCount; ++
i) {
1517 d->channels[
i].ignoreSslErrors(errors);
1521 d->channels[
channel].ignoreSslErrors(errors);
1529 d_func()->preConnectRequests--;
1535 return d->peerVerifyName;
1541 d->peerVerifyName = peerName;
1554 for (
int i = 0;
i <
d->activeChannelCount;
i++) {
1561 d->connectionMonitor.stopMonitoring();
1564#ifndef QT_NO_NETWORKPROXY
1575 && (chan->switchedToHttp2 || chan->h2RequestsToSend.size() > 0))
1580 Q_ASSERT(chan->h2RequestsToSend.size() > 0);
1581 reply = chan->h2RequestsToSend.cbegin().value().second;
1583 reply = chan->reply;
1597#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.
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)