Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/network/socket/qhttpsocketengine.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||||||||
2 | ** | - | ||||||||||||||||||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||||||||
5 | ** | - | ||||||||||||||||||
6 | ** This file is part of the QtNetwork module of the Qt Toolkit. | - | ||||||||||||||||||
7 | ** | - | ||||||||||||||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||||||||
9 | ** Commercial License Usage | - | ||||||||||||||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||||||||
16 | ** | - | ||||||||||||||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||||||||||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||||||||
24 | ** | - | ||||||||||||||||||
25 | ** GNU General Public License Usage | - | ||||||||||||||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||||||||
35 | ** | - | ||||||||||||||||||
36 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||
37 | ** | - | ||||||||||||||||||
38 | ****************************************************************************/ | - | ||||||||||||||||||
39 | - | |||||||||||||||||||
40 | #include "qhttpsocketengine_p.h" | - | ||||||||||||||||||
41 | #include "qtcpsocket.h" | - | ||||||||||||||||||
42 | #include "qhostaddress.h" | - | ||||||||||||||||||
43 | #include "qurl.h" | - | ||||||||||||||||||
44 | #include "private/qhttpnetworkreply_p.h" | - | ||||||||||||||||||
45 | #include "private/qiodevice_p.h" | - | ||||||||||||||||||
46 | #include "qelapsedtimer.h" | - | ||||||||||||||||||
47 | #include "qnetworkinterface.h" | - | ||||||||||||||||||
48 | - | |||||||||||||||||||
49 | #if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP) | - | ||||||||||||||||||
50 | #include <qdebug.h> | - | ||||||||||||||||||
51 | - | |||||||||||||||||||
52 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||
53 | - | |||||||||||||||||||
54 | #define DEBUG | - | ||||||||||||||||||
55 | - | |||||||||||||||||||
56 | QHttpSocketEngine::QHttpSocketEngine(QObject *parent) | - | ||||||||||||||||||
57 | : QAbstractSocketEngine(*new QHttpSocketEnginePrivate, parent) | - | ||||||||||||||||||
58 | { | - | ||||||||||||||||||
59 | } | - | ||||||||||||||||||
60 | - | |||||||||||||||||||
61 | QHttpSocketEngine::~QHttpSocketEngine() | - | ||||||||||||||||||
62 | { | - | ||||||||||||||||||
63 | } | - | ||||||||||||||||||
64 | - | |||||||||||||||||||
65 | bool QHttpSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol) | - | ||||||||||||||||||
66 | { | - | ||||||||||||||||||
67 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
68 | if (type != QAbstractSocket::TcpSocket) | - | ||||||||||||||||||
69 | return false; | - | ||||||||||||||||||
70 | - | |||||||||||||||||||
71 | setProtocol(protocol); | - | ||||||||||||||||||
72 | setSocketType(type); | - | ||||||||||||||||||
73 | d->socket = new QTcpSocket(this); | - | ||||||||||||||||||
74 | d->reply = new QHttpNetworkReply(QUrl(), this); | - | ||||||||||||||||||
75 | #ifndef QT_NO_BEARERMANAGEMENT | - | ||||||||||||||||||
76 | d->socket->setProperty("_q_networkSession", property("_q_networkSession")); | - | ||||||||||||||||||
77 | #endif | - | ||||||||||||||||||
78 | - | |||||||||||||||||||
79 | // Explicitly disable proxying on the proxy socket itself to avoid | - | ||||||||||||||||||
80 | // unwanted recursion. | - | ||||||||||||||||||
81 | d->socket->setProxy(QNetworkProxy::NoProxy); | - | ||||||||||||||||||
82 | - | |||||||||||||||||||
83 | // Intercept all the signals. | - | ||||||||||||||||||
84 | connect(d->socket, SIGNAL(connected()), | - | ||||||||||||||||||
85 | this, SLOT(slotSocketConnected()), | - | ||||||||||||||||||
86 | Qt::DirectConnection); | - | ||||||||||||||||||
87 | connect(d->socket, SIGNAL(disconnected()), | - | ||||||||||||||||||
88 | this, SLOT(slotSocketDisconnected()), | - | ||||||||||||||||||
89 | Qt::DirectConnection); | - | ||||||||||||||||||
90 | connect(d->socket, SIGNAL(readyRead()), | - | ||||||||||||||||||
91 | this, SLOT(slotSocketReadNotification()), | - | ||||||||||||||||||
92 | Qt::DirectConnection); | - | ||||||||||||||||||
93 | connect(d->socket, SIGNAL(bytesWritten(qint64)), | - | ||||||||||||||||||
94 | this, SLOT(slotSocketBytesWritten()), | - | ||||||||||||||||||
95 | Qt::DirectConnection); | - | ||||||||||||||||||
96 | connect(d->socket, SIGNAL(error(QAbstractSocket::SocketError)), | - | ||||||||||||||||||
97 | this, SLOT(slotSocketError(QAbstractSocket::SocketError)), | - | ||||||||||||||||||
98 | Qt::DirectConnection); | - | ||||||||||||||||||
99 | connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), | - | ||||||||||||||||||
100 | this, SLOT(slotSocketStateChanged(QAbstractSocket::SocketState)), | - | ||||||||||||||||||
101 | Qt::DirectConnection); | - | ||||||||||||||||||
102 | - | |||||||||||||||||||
103 | return true; | - | ||||||||||||||||||
104 | } | - | ||||||||||||||||||
105 | - | |||||||||||||||||||
106 | bool QHttpSocketEngine::initialize(qintptr, QAbstractSocket::SocketState) | - | ||||||||||||||||||
107 | { | - | ||||||||||||||||||
108 | return false; | - | ||||||||||||||||||
109 | } | - | ||||||||||||||||||
110 | - | |||||||||||||||||||
111 | void QHttpSocketEngine::setProxy(const QNetworkProxy &proxy) | - | ||||||||||||||||||
112 | { | - | ||||||||||||||||||
113 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
114 | d->proxy = proxy; | - | ||||||||||||||||||
115 | QString user = proxy.user(); | - | ||||||||||||||||||
116 | if (!user.isEmpty()) | - | ||||||||||||||||||
117 | d->authenticator.setUser(user); | - | ||||||||||||||||||
118 | QString password = proxy.password(); | - | ||||||||||||||||||
119 | if (!password.isEmpty()) | - | ||||||||||||||||||
120 | d->authenticator.setPassword(password); | - | ||||||||||||||||||
121 | } | - | ||||||||||||||||||
122 | - | |||||||||||||||||||
123 | qintptr QHttpSocketEngine::socketDescriptor() const | - | ||||||||||||||||||
124 | { | - | ||||||||||||||||||
125 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
126 | return d->socket ? d->socket->socketDescriptor() : -1; | - | ||||||||||||||||||
127 | } | - | ||||||||||||||||||
128 | - | |||||||||||||||||||
129 | bool QHttpSocketEngine::isValid() const | - | ||||||||||||||||||
130 | { | - | ||||||||||||||||||
131 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
132 | return d->socket; | - | ||||||||||||||||||
133 | } | - | ||||||||||||||||||
134 | - | |||||||||||||||||||
135 | bool QHttpSocketEngine::connectInternal() | - | ||||||||||||||||||
136 | { | - | ||||||||||||||||||
137 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
138 | - | |||||||||||||||||||
139 | d->credentialsSent = false; | - | ||||||||||||||||||
140 | - | |||||||||||||||||||
141 | // If the handshake is done, enter ConnectedState state and return true. | - | ||||||||||||||||||
142 | if (d->state == Connected) { | - | ||||||||||||||||||
143 | qWarning("QHttpSocketEngine::connectToHost: called when already connected"); | - | ||||||||||||||||||
144 | setState(QAbstractSocket::ConnectedState); | - | ||||||||||||||||||
145 | return true; | - | ||||||||||||||||||
146 | } | - | ||||||||||||||||||
147 | - | |||||||||||||||||||
148 | if (d->state == ConnectSent && d->socketState != QAbstractSocket::ConnectedState) | - | ||||||||||||||||||
149 | setState(QAbstractSocket::UnconnectedState); | - | ||||||||||||||||||
150 | - | |||||||||||||||||||
151 | // Handshake isn't done. If unconnected, start connecting. | - | ||||||||||||||||||
152 | if (d->state == None && d->socket->state() == QAbstractSocket::UnconnectedState) { | - | ||||||||||||||||||
153 | setState(QAbstractSocket::ConnectingState); | - | ||||||||||||||||||
154 | //limit buffer in internal socket, data is buffered in the external socket under application control | - | ||||||||||||||||||
155 | d->socket->setReadBufferSize(65536); | - | ||||||||||||||||||
156 | d->socket->connectToHost(d->proxy.hostName(), d->proxy.port()); | - | ||||||||||||||||||
157 | } | - | ||||||||||||||||||
158 | - | |||||||||||||||||||
159 | // If connected (might happen right away, at least for localhost services | - | ||||||||||||||||||
160 | // on some BSD systems), there might already be bytes available. | - | ||||||||||||||||||
161 | if (bytesAvailable()) | - | ||||||||||||||||||
162 | slotSocketReadNotification(); | - | ||||||||||||||||||
163 | - | |||||||||||||||||||
164 | return d->socketState == QAbstractSocket::ConnectedState; | - | ||||||||||||||||||
165 | } | - | ||||||||||||||||||
166 | - | |||||||||||||||||||
167 | bool QHttpSocketEngine::connectToHost(const QHostAddress &address, quint16 port) | - | ||||||||||||||||||
168 | { | - | ||||||||||||||||||
169 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
170 | - | |||||||||||||||||||
171 | setPeerAddress(address); | - | ||||||||||||||||||
172 | setPeerPort(port); | - | ||||||||||||||||||
173 | d->peerName.clear(); | - | ||||||||||||||||||
174 | - | |||||||||||||||||||
175 | return connectInternal(); | - | ||||||||||||||||||
176 | } | - | ||||||||||||||||||
177 | - | |||||||||||||||||||
178 | bool QHttpSocketEngine::connectToHostByName(const QString &hostname, quint16 port) | - | ||||||||||||||||||
179 | { | - | ||||||||||||||||||
180 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
181 | - | |||||||||||||||||||
182 | setPeerAddress(QHostAddress()); | - | ||||||||||||||||||
183 | setPeerPort(port); | - | ||||||||||||||||||
184 | d->peerName = hostname; | - | ||||||||||||||||||
185 | - | |||||||||||||||||||
186 | return connectInternal(); | - | ||||||||||||||||||
187 | } | - | ||||||||||||||||||
188 | - | |||||||||||||||||||
189 | bool QHttpSocketEngine::bind(const QHostAddress &, quint16) | - | ||||||||||||||||||
190 | { | - | ||||||||||||||||||
191 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
192 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
193 | QLatin1String("Unsupported socket operation")); | - | ||||||||||||||||||
194 | return false; never executed: return false; | 0 | ||||||||||||||||||
195 | } | - | ||||||||||||||||||
196 | - | |||||||||||||||||||
197 | bool QHttpSocketEngine::listen() | - | ||||||||||||||||||
198 | { | - | ||||||||||||||||||
199 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
200 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
201 | QLatin1String("Unsupported socket operation")); | - | ||||||||||||||||||
202 | return false; never executed: return false; | 0 | ||||||||||||||||||
203 | } | - | ||||||||||||||||||
204 | - | |||||||||||||||||||
205 | int QHttpSocketEngine::accept() | - | ||||||||||||||||||
206 | { | - | ||||||||||||||||||
207 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
208 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
209 | QLatin1String("Unsupported socket operation")); | - | ||||||||||||||||||
210 | return 0-1; never executed: return -1; | 0 | ||||||||||||||||||
211 | } | - | ||||||||||||||||||
212 | - | |||||||||||||||||||
213 | void QHttpSocketEngine::close() | - | ||||||||||||||||||
214 | { | - | ||||||||||||||||||
215 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
216 | if (d->socket) { | - | ||||||||||||||||||
217 | d->socket->close(); | - | ||||||||||||||||||
218 | delete d->socket; | - | ||||||||||||||||||
219 | d->socket = 0; | - | ||||||||||||||||||
220 | } | - | ||||||||||||||||||
221 | } | - | ||||||||||||||||||
222 | - | |||||||||||||||||||
223 | qint64 QHttpSocketEngine::bytesAvailable() const | - | ||||||||||||||||||
224 | { | - | ||||||||||||||||||
225 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
226 | return d->socket ? d->socket->bytesAvailable() : 0; | - | ||||||||||||||||||
227 | } | - | ||||||||||||||||||
228 | - | |||||||||||||||||||
229 | qint64 QHttpSocketEngine::read(char *data, qint64 maxlen) | - | ||||||||||||||||||
230 | { | - | ||||||||||||||||||
231 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
232 | qint64 bytesRead = d->socket->read(data, maxlen); | - | ||||||||||||||||||
233 | - | |||||||||||||||||||
234 | if (d->socket->state() == QAbstractSocket::UnconnectedState | - | ||||||||||||||||||
235 | && d->socket->bytesAvailable() == 0) { | - | ||||||||||||||||||
236 | emitReadNotification(); | - | ||||||||||||||||||
237 | } | - | ||||||||||||||||||
238 | - | |||||||||||||||||||
239 | if (bytesRead == -1) { | - | ||||||||||||||||||
240 | // If nothing has been read so far, and the direct socket read | - | ||||||||||||||||||
241 | // failed, return the socket's error. Otherwise, fall through and | - | ||||||||||||||||||
242 | // return as much as we read so far. | - | ||||||||||||||||||
243 | close(); | - | ||||||||||||||||||
244 | setError(QAbstractSocket::RemoteHostClosedError, | - | ||||||||||||||||||
245 | QLatin1String("Remote host closed")); | - | ||||||||||||||||||
246 | setState(QAbstractSocket::UnconnectedState); | - | ||||||||||||||||||
247 | return -1; | - | ||||||||||||||||||
248 | } | - | ||||||||||||||||||
249 | return bytesRead; | - | ||||||||||||||||||
250 | } | - | ||||||||||||||||||
251 | - | |||||||||||||||||||
252 | qint64 QHttpSocketEngine::write(const char *data, qint64 len) | - | ||||||||||||||||||
253 | { | - | ||||||||||||||||||
254 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
255 | return d->socket->write(data, len); | - | ||||||||||||||||||
256 | } | - | ||||||||||||||||||
257 | - | |||||||||||||||||||
258 | #ifndef QT_NO_UDPSOCKET | - | ||||||||||||||||||
259 | #ifndef QT_NO_NETWORKINTERFACE | - | ||||||||||||||||||
260 | bool QHttpSocketEngine::joinMulticastGroup(const QHostAddress &, | - | ||||||||||||||||||
261 | const QNetworkInterface &) | - | ||||||||||||||||||
262 | { | - | ||||||||||||||||||
263 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
264 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
265 | QLatin1String("Operation on"Unsupported socket is not supported"operation")); | - | ||||||||||||||||||
266 | return false; never executed: return false; | 0 | ||||||||||||||||||
267 | } | - | ||||||||||||||||||
268 | - | |||||||||||||||||||
269 | bool QHttpSocketEngine::leaveMulticastGroup(const QHostAddress &, | - | ||||||||||||||||||
270 | const QNetworkInterface &) | - | ||||||||||||||||||
271 | { | - | ||||||||||||||||||
272 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
273 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
274 | QLatin1String("Operation on"Unsupported socket is not supported"operation")); | - | ||||||||||||||||||
275 | return false; never executed: return false; | 0 | ||||||||||||||||||
276 | } | - | ||||||||||||||||||
277 | - | |||||||||||||||||||
278 | QNetworkInterface QHttpSocketEngine::multicastInterface() const | - | ||||||||||||||||||
279 | { | - | ||||||||||||||||||
280 | return QNetworkInterface(); | - | ||||||||||||||||||
281 | } | - | ||||||||||||||||||
282 | - | |||||||||||||||||||
283 | bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &) | - | ||||||||||||||||||
284 | { | - | ||||||||||||||||||
285 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
286 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
287 | QLatin1String("Operation on"Unsupported socket is not supported"operation")); | - | ||||||||||||||||||
288 | return false; never executed: return false; | 0 | ||||||||||||||||||
289 | } | - | ||||||||||||||||||
290 | #endif // QT_NO_NETWORKINTERFACE | - | ||||||||||||||||||
291 | - | |||||||||||||||||||
292 | qint64 QHttpSocketEngine::readDatagram(char *, qint64, QIpPacketHeader *, PacketHeaderOptions) | - | ||||||||||||||||||
293 | { | - | ||||||||||||||||||
294 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
295 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
296 | QLatin1String("Unsupported socket operation")); | - | ||||||||||||||||||
297 | return 0-1; never executed: return -1; | 0 | ||||||||||||||||||
298 | } | - | ||||||||||||||||||
299 | - | |||||||||||||||||||
300 | qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QIpPacketHeader &) | - | ||||||||||||||||||
301 | { | - | ||||||||||||||||||
302 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
303 | setError(QAbstractSocket::UnsupportedSocketOperationError, | - | ||||||||||||||||||
304 | QLatin1String("Unsupported socket operation")); | - | ||||||||||||||||||
305 | return 0-1; never executed: return -1; | 0 | ||||||||||||||||||
306 | } | - | ||||||||||||||||||
307 | - | |||||||||||||||||||
308 | bool QHttpSocketEngine::hasPendingDatagrams() const | - | ||||||||||||||||||
309 | { | - | ||||||||||||||||||
310 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
311 | return false; executed 1 time by 1 test: return false; Executed by:
| 1 | ||||||||||||||||||
312 | } | - | ||||||||||||||||||
313 | - | |||||||||||||||||||
314 | qint64 QHttpSocketEngine::pendingDatagramSize() const | - | ||||||||||||||||||
315 | { | - | ||||||||||||||||||
316 | qWarning("Operation is not supported"); | - | ||||||||||||||||||
317 | return 0-1; never executed: return -1; | 0 | ||||||||||||||||||
318 | } | - | ||||||||||||||||||
319 | #endif // QT_NO_UDPSOCKET | - | ||||||||||||||||||
320 | - | |||||||||||||||||||
321 | qint64 QHttpSocketEngine::bytesToWrite() const | - | ||||||||||||||||||
322 | { | - | ||||||||||||||||||
323 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
324 | if (d->socket) { | - | ||||||||||||||||||
325 | return d->socket->bytesToWrite(); | - | ||||||||||||||||||
326 | } else { | - | ||||||||||||||||||
327 | return 0; | - | ||||||||||||||||||
328 | } | - | ||||||||||||||||||
329 | } | - | ||||||||||||||||||
330 | - | |||||||||||||||||||
331 | int QHttpSocketEngine::option(SocketOption option) const | - | ||||||||||||||||||
332 | { | - | ||||||||||||||||||
333 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
334 | if (d->socket) { | - | ||||||||||||||||||
335 | // convert the enum and call the real socket | - | ||||||||||||||||||
336 | if (option == QAbstractSocketEngine::LowDelayOption) | - | ||||||||||||||||||
337 | return d->socket->socketOption(QAbstractSocket::LowDelayOption).toInt(); | - | ||||||||||||||||||
338 | if (option == QAbstractSocketEngine::KeepAliveOption) | - | ||||||||||||||||||
339 | return d->socket->socketOption(QAbstractSocket::KeepAliveOption).toInt(); | - | ||||||||||||||||||
340 | } | - | ||||||||||||||||||
341 | return -1; | - | ||||||||||||||||||
342 | } | - | ||||||||||||||||||
343 | - | |||||||||||||||||||
344 | bool QHttpSocketEngine::setOption(SocketOption option, int value) | - | ||||||||||||||||||
345 | { | - | ||||||||||||||||||
346 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
347 | if (d->socket) { | - | ||||||||||||||||||
348 | // convert the enum and call the real socket | - | ||||||||||||||||||
349 | if (option == QAbstractSocketEngine::LowDelayOption) | - | ||||||||||||||||||
350 | d->socket->setSocketOption(QAbstractSocket::LowDelayOption, value); | - | ||||||||||||||||||
351 | if (option == QAbstractSocketEngine::KeepAliveOption) | - | ||||||||||||||||||
352 | d->socket->setSocketOption(QAbstractSocket::KeepAliveOption, value); | - | ||||||||||||||||||
353 | return true; | - | ||||||||||||||||||
354 | } | - | ||||||||||||||||||
355 | return false; | - | ||||||||||||||||||
356 | } | - | ||||||||||||||||||
357 | - | |||||||||||||||||||
358 | bool QHttpSocketEngine::waitForRead(int msecs, bool *timedOut) | - | ||||||||||||||||||
359 | { | - | ||||||||||||||||||
360 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
361 | - | |||||||||||||||||||
362 | if (!d->socket || d->socket->state() == QAbstractSocket::UnconnectedState) | - | ||||||||||||||||||
363 | return false; | - | ||||||||||||||||||
364 | - | |||||||||||||||||||
365 | QElapsedTimer stopWatch; | - | ||||||||||||||||||
366 | stopWatch.start(); | - | ||||||||||||||||||
367 | - | |||||||||||||||||||
368 | // Wait for more data if nothing is available. | - | ||||||||||||||||||
369 | if (!d->socket->bytesAvailable()) { | - | ||||||||||||||||||
370 | if (!d->socket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { | - | ||||||||||||||||||
371 | if (d->socket->state() == QAbstractSocket::UnconnectedState) | - | ||||||||||||||||||
372 | return true; | - | ||||||||||||||||||
373 | setError(d->socket->error(), d->socket->errorString()); | - | ||||||||||||||||||
374 | if (timedOut && d->socket->error() == QAbstractSocket::SocketTimeoutError) | - | ||||||||||||||||||
375 | *timedOut = true; | - | ||||||||||||||||||
376 | return false; | - | ||||||||||||||||||
377 | } | - | ||||||||||||||||||
378 | } | - | ||||||||||||||||||
379 | - | |||||||||||||||||||
380 | // If we're not connected yet, wait until we are, or until an error | - | ||||||||||||||||||
381 | // occurs. | - | ||||||||||||||||||
382 | while (d->state != Connected && d->socket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { | - | ||||||||||||||||||
383 | // Loop while the protocol handshake is taking place. | - | ||||||||||||||||||
384 | } | - | ||||||||||||||||||
385 | - | |||||||||||||||||||
386 | // Report any error that may occur. | - | ||||||||||||||||||
387 | if (d->state != Connected) { | - | ||||||||||||||||||
388 | setError(d->socket->error(), d->socket->errorString()); | - | ||||||||||||||||||
389 | if (timedOut && d->socket->error() == QAbstractSocket::SocketTimeoutError) | - | ||||||||||||||||||
390 | *timedOut = true; | - | ||||||||||||||||||
391 | return false; | - | ||||||||||||||||||
392 | } | - | ||||||||||||||||||
393 | return true; | - | ||||||||||||||||||
394 | } | - | ||||||||||||||||||
395 | - | |||||||||||||||||||
396 | bool QHttpSocketEngine::waitForWrite(int msecs, bool *timedOut) | - | ||||||||||||||||||
397 | { | - | ||||||||||||||||||
398 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
399 | - | |||||||||||||||||||
400 | // If we're connected, just forward the call. | - | ||||||||||||||||||
401 | if (d->state == Connected) { | - | ||||||||||||||||||
402 | if (d->socket->bytesToWrite()) { | - | ||||||||||||||||||
403 | if (!d->socket->waitForBytesWritten(msecs)) { | - | ||||||||||||||||||
404 | if (d->socket->error() == QAbstractSocket::SocketTimeoutError && timedOut) | - | ||||||||||||||||||
405 | *timedOut = true; | - | ||||||||||||||||||
406 | return false; | - | ||||||||||||||||||
407 | } | - | ||||||||||||||||||
408 | } | - | ||||||||||||||||||
409 | return true; | - | ||||||||||||||||||
410 | } | - | ||||||||||||||||||
411 | - | |||||||||||||||||||
412 | QElapsedTimer stopWatch; | - | ||||||||||||||||||
413 | stopWatch.start(); | - | ||||||||||||||||||
414 | - | |||||||||||||||||||
415 | // If we're not connected yet, wait until we are, and until bytes have | - | ||||||||||||||||||
416 | // been received (i.e., the socket has connected, we have sent the | - | ||||||||||||||||||
417 | // greeting, and then received the response). | - | ||||||||||||||||||
418 | while (d->state != Connected && d->socket->waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { | - | ||||||||||||||||||
419 | // Loop while the protocol handshake is taking place. | - | ||||||||||||||||||
420 | } | - | ||||||||||||||||||
421 | - | |||||||||||||||||||
422 | // Report any error that may occur. | - | ||||||||||||||||||
423 | if (d->state != Connected) { | - | ||||||||||||||||||
424 | // setError(d->socket->error(), d->socket->errorString()); | - | ||||||||||||||||||
425 | if (timedOut && d->socket->error() == QAbstractSocket::SocketTimeoutError) | - | ||||||||||||||||||
426 | *timedOut = true; | - | ||||||||||||||||||
427 | } | - | ||||||||||||||||||
428 | - | |||||||||||||||||||
429 | return true; | - | ||||||||||||||||||
430 | } | - | ||||||||||||||||||
431 | - | |||||||||||||||||||
432 | bool QHttpSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, | - | ||||||||||||||||||
433 | bool checkRead, bool checkWrite, | - | ||||||||||||||||||
434 | int msecs, bool *timedOut) | - | ||||||||||||||||||
435 | { | - | ||||||||||||||||||
436 | Q_UNUSED(checkRead); | - | ||||||||||||||||||
437 | - | |||||||||||||||||||
438 | if (!checkWrite) { | - | ||||||||||||||||||
439 | // Not interested in writing? Then we wait for read notifications. | - | ||||||||||||||||||
440 | bool canRead = waitForRead(msecs, timedOut); | - | ||||||||||||||||||
441 | if (readyToRead) | - | ||||||||||||||||||
442 | *readyToRead = canRead; | - | ||||||||||||||||||
443 | return canRead; | - | ||||||||||||||||||
444 | } | - | ||||||||||||||||||
445 | - | |||||||||||||||||||
446 | // Interested in writing? Then we wait for write notifications. | - | ||||||||||||||||||
447 | bool canWrite = waitForWrite(msecs, timedOut); | - | ||||||||||||||||||
448 | if (readyToWrite) | - | ||||||||||||||||||
449 | *readyToWrite = canWrite; | - | ||||||||||||||||||
450 | return canWrite; | - | ||||||||||||||||||
451 | } | - | ||||||||||||||||||
452 | - | |||||||||||||||||||
453 | bool QHttpSocketEngine::isReadNotificationEnabled() const | - | ||||||||||||||||||
454 | { | - | ||||||||||||||||||
455 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
456 | return d->readNotificationEnabled; | - | ||||||||||||||||||
457 | } | - | ||||||||||||||||||
458 | - | |||||||||||||||||||
459 | void QHttpSocketEngine::setReadNotificationEnabled(bool enable) | - | ||||||||||||||||||
460 | { | - | ||||||||||||||||||
461 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
462 | if (d->readNotificationEnabled == enable) | - | ||||||||||||||||||
463 | return; | - | ||||||||||||||||||
464 | - | |||||||||||||||||||
465 | d->readNotificationEnabled = enable; | - | ||||||||||||||||||
466 | if (enable) { | - | ||||||||||||||||||
467 | // Enabling read notification can trigger a notification. | - | ||||||||||||||||||
468 | if (bytesAvailable()) { | - | ||||||||||||||||||
469 | slotSocketReadNotification(); | - | ||||||||||||||||||
470 | } else if (d->socket && d->socket->state() == QAbstractSocket::UnconnectedState) { | - | ||||||||||||||||||
471 | emitReadNotification(); | - | ||||||||||||||||||
472 | } | - | ||||||||||||||||||
473 | } | - | ||||||||||||||||||
474 | } | - | ||||||||||||||||||
475 | - | |||||||||||||||||||
476 | bool QHttpSocketEngine::isWriteNotificationEnabled() const | - | ||||||||||||||||||
477 | { | - | ||||||||||||||||||
478 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
479 | return d->writeNotificationEnabled; | - | ||||||||||||||||||
480 | } | - | ||||||||||||||||||
481 | - | |||||||||||||||||||
482 | void QHttpSocketEngine::setWriteNotificationEnabled(bool enable) | - | ||||||||||||||||||
483 | { | - | ||||||||||||||||||
484 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
485 | d->writeNotificationEnabled = enable; | - | ||||||||||||||||||
486 | if (enable && d->state == Connected && d->socket->state() == QAbstractSocket::ConnectedState) | - | ||||||||||||||||||
487 | QMetaObject::invokeMethod(this, "writeNotification", Qt::QueuedConnection); | - | ||||||||||||||||||
488 | } | - | ||||||||||||||||||
489 | - | |||||||||||||||||||
490 | bool QHttpSocketEngine::isExceptionNotificationEnabled() const | - | ||||||||||||||||||
491 | { | - | ||||||||||||||||||
492 | Q_D(const QHttpSocketEngine); | - | ||||||||||||||||||
493 | return d->exceptNotificationEnabled; | - | ||||||||||||||||||
494 | } | - | ||||||||||||||||||
495 | - | |||||||||||||||||||
496 | void QHttpSocketEngine::setExceptionNotificationEnabled(bool enable) | - | ||||||||||||||||||
497 | { | - | ||||||||||||||||||
498 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
499 | d->exceptNotificationEnabled = enable; | - | ||||||||||||||||||
500 | } | - | ||||||||||||||||||
501 | - | |||||||||||||||||||
502 | void QHttpSocketEngine::slotSocketConnected() | - | ||||||||||||||||||
503 | { | - | ||||||||||||||||||
504 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
505 | - | |||||||||||||||||||
506 | // Send the greeting. | - | ||||||||||||||||||
507 | const char method[] = "CONNECT"; | - | ||||||||||||||||||
508 | QByteArray peerAddress = d->peerName.isEmpty() ?
| 49-482 | ||||||||||||||||||
509 | d->peerAddress.toString().toLatin1() : | - | ||||||||||||||||||
510 | QUrl::toAce(d->peerName); | - | ||||||||||||||||||
511 | QByteArray path = peerAddress + ':' + QByteArray::number(d->peerPort); | - | ||||||||||||||||||
512 | QByteArray data = method; | - | ||||||||||||||||||
513 | data += ' '; | - | ||||||||||||||||||
514 | data += path; | - | ||||||||||||||||||
515 | data += " HTTP/1.1\r\n"; | - | ||||||||||||||||||
516 | data += "Proxy-Connection: keep-alive\r\n"; | - | ||||||||||||||||||
517 | data += "Host: " + peerAddress + "\r\n"; | - | ||||||||||||||||||
518 | if (!d->proxy.hasRawHeader("User-Agent"))
| 13-518 | ||||||||||||||||||
519 | data += "User-Agent: Mozilla/5.0\r\n"; executed 518 times by 7 tests: data += "User-Agent: Mozilla/5.0\r\n"; Executed by:
| 518 | ||||||||||||||||||
520 | foreach (const QByteArray &header,auto headers = d->proxy.rawHeaderList()) {(); | - | ||||||||||||||||||
521 | for (const QByteArray &header : headers) | - | ||||||||||||||||||
522 | data += header + ": " + d->proxy.rawHeader(header) + "\r\n"; executed 13 times by 1 test: data += header + ": " + d->proxy.rawHeader(header) + "\r\n"; Executed by:
| 13 | ||||||||||||||||||
523 | }QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator); | - | ||||||||||||||||||
524 | //qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1); | - | ||||||||||||||||||
525 | if (priv && priv->method != QAuthenticatorPrivate::None) {
| 6-357 | ||||||||||||||||||
526 | d->credentialsSent = true; | - | ||||||||||||||||||
527 | data += "Proxy-Authorization: " + priv->calculateResponse(method, path); | - | ||||||||||||||||||
528 | data += "\r\n"; | - | ||||||||||||||||||
529 | } executed 168 times by 7 tests: end of block Executed by:
| 168 | ||||||||||||||||||
530 | data += "\r\n"; | - | ||||||||||||||||||
531 | // qDebug() << ">>>>>>>> sending request" << this; | - | ||||||||||||||||||
532 | // qDebug() << data; | - | ||||||||||||||||||
533 | // qDebug(">>>>>>>"); | - | ||||||||||||||||||
534 | d->socket->write(data); | - | ||||||||||||||||||
535 | d->state = ConnectSent; | - | ||||||||||||||||||
536 | } executed 531 times by 7 tests: end of block Executed by:
| 531 | ||||||||||||||||||
537 | - | |||||||||||||||||||
538 | void QHttpSocketEngine::slotSocketDisconnected() | - | ||||||||||||||||||
539 | { | - | ||||||||||||||||||
540 | } | - | ||||||||||||||||||
541 | - | |||||||||||||||||||
542 | void QHttpSocketEngine::slotSocketReadNotification() | - | ||||||||||||||||||
543 | { | - | ||||||||||||||||||
544 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
545 | if (d->state != Connected && d->socket->bytesAvailable() == 0)
| 0-3183 | ||||||||||||||||||
546 | return; never executed: return; | 0 | ||||||||||||||||||
547 | - | |||||||||||||||||||
548 | if (d->state == Connected) {
| 628-3183 | ||||||||||||||||||
549 | // Forward as a read notification. | - | ||||||||||||||||||
550 | if (d->readNotificationEnabled)
| 28-3155 | ||||||||||||||||||
551 | emitReadNotification(); executed 3155 times by 7 tests: emitReadNotification(); Executed by:
| 3155 | ||||||||||||||||||
552 | return; executed 3183 times by 7 tests: return; Executed by:
| 3183 | ||||||||||||||||||
553 | } | - | ||||||||||||||||||
554 | - | |||||||||||||||||||
555 | if (d->state == ConnectSent) {
| 116-512 | ||||||||||||||||||
556 | d->reply->d_func()->state = QHttpNetworkReplyPrivate::NothingDoneState; | - | ||||||||||||||||||
557 | d->state = ReadResponseHeader; | - | ||||||||||||||||||
558 | } executed 512 times by 7 tests: end of block Executed by:
| 512 | ||||||||||||||||||
559 | - | |||||||||||||||||||
560 | if (d->state == ReadResponseHeader) {
| 116-512 | ||||||||||||||||||
561 | bool ok = readHttpHeader(); | - | ||||||||||||||||||
562 | if (!ok) {
| 2-510 | ||||||||||||||||||
563 | // protocol error, this isn't HTTP | - | ||||||||||||||||||
564 | d->socket->close(); | - | ||||||||||||||||||
565 | setState(QAbstractSocket::UnconnectedState); | - | ||||||||||||||||||
566 | setError(QAbstractSocket::ProxyProtocolError, tr("Did not receive HTTP response from proxy")); | - | ||||||||||||||||||
567 | emitConnectionNotification(); | - | ||||||||||||||||||
568 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||||||||||||||
569 | } | - | ||||||||||||||||||
570 | if (d->state == ReadResponseHeader)
| 0-510 | ||||||||||||||||||
571 | return; // readHttpHeader() was not done yet, need to wait for more header data never executed: return; | 0 | ||||||||||||||||||
572 | } executed 510 times by 7 tests: end of block Executed by:
| 510 | ||||||||||||||||||
573 | - | |||||||||||||||||||
574 | if (d->state == ReadResponseContent) {
| 0-626 | ||||||||||||||||||
575 | char dummybuffer[4096]; | - | ||||||||||||||||||
576 | while (d->pendingResponseData) {
| 413-510 | ||||||||||||||||||
577 | int read = d->socket->read(dummybuffer, qMin(sizeof(dummybuffer), (size_t)d->pendingResponseData)); | - | ||||||||||||||||||
578 | if (read == 0)
| 116-297 | ||||||||||||||||||
579 | return; executed 116 times by 7 tests: return; Executed by:
| 116 | ||||||||||||||||||
580 | if (read == -1) {
| 0-297 | ||||||||||||||||||
581 | d->socket->disconnectFromHost(); | - | ||||||||||||||||||
582 | emitWriteNotification(); | - | ||||||||||||||||||
583 | return; never executed: return; | 0 | ||||||||||||||||||
584 | } | - | ||||||||||||||||||
585 | d->pendingResponseData -= read; | - | ||||||||||||||||||
586 | } executed 297 times by 7 tests: end of block Executed by:
| 297 | ||||||||||||||||||
587 | if (d->pendingResponseData > 0)
| 0-510 | ||||||||||||||||||
588 | return; never executed: return; | 0 | ||||||||||||||||||
589 | if (d->reply->d_func()->statusCode == 407)
| 176-334 | ||||||||||||||||||
590 | d->state = SendAuthentication; executed 176 times by 7 tests: d->state = SendAuthentication; Executed by:
| 176 | ||||||||||||||||||
591 | } executed 510 times by 7 tests: end of block Executed by:
| 510 | ||||||||||||||||||
592 | - | |||||||||||||||||||
593 | int statusCode = d->reply->statusCode(); | - | ||||||||||||||||||
594 | QAuthenticatorPrivate *priv = 0; | - | ||||||||||||||||||
595 | if (statusCode == 200) {
| 198-312 | ||||||||||||||||||
596 | d->state = Connected; | - | ||||||||||||||||||
597 | setLocalAddress(d->socket->localAddress()); | - | ||||||||||||||||||
598 | setLocalPort(d->socket->localPort()); | - | ||||||||||||||||||
599 | d->inboundStreamCount = d->outboundStreamCount = 1; | - | ||||||||||||||||||
600 | setState(QAbstractSocket::ConnectedState); | - | ||||||||||||||||||
601 | d->authenticator.detach(); | - | ||||||||||||||||||
602 | priv = QAuthenticatorPrivate::getPrivate(d->authenticator); | - | ||||||||||||||||||
603 | priv->hasFailed = false; | - | ||||||||||||||||||
604 | } else if (statusCode == 407) { executed 312 times by 7 tests: end of block Executed by:
| 22-312 | ||||||||||||||||||
605 | if (d->authenticator.isNull())
| 10-166 | ||||||||||||||||||
606 | d->authenticator.detach(); executed 166 times by 6 tests: d->authenticator.detach(); Executed by:
| 166 | ||||||||||||||||||
607 | priv = QAuthenticatorPrivate::getPrivate(d->authenticator); | - | ||||||||||||||||||
608 | - | |||||||||||||||||||
609 | if (d->credentialsSent && priv->phase != QAuthenticatorPrivate::Phase2) {
| 0-171 | ||||||||||||||||||
610 | // Remember that (e.g.) NTLM is two-phase, so only reset when the authentication is not currently in progress. | - | ||||||||||||||||||
611 | //407 response again means the provided username/password were invalid. | - | ||||||||||||||||||
612 | d->authenticator = QAuthenticator(); //this is needed otherwise parseHttpResponse won't set the state, and then signal isn't emitted. | - | ||||||||||||||||||
613 | d->authenticator.detach(); | - | ||||||||||||||||||
614 | priv = QAuthenticatorPrivate::getPrivate(d->authenticator); | - | ||||||||||||||||||
615 | priv->hasFailed = true; | - | ||||||||||||||||||
616 | } executed 5 times by 2 tests: end of block Executed by:
| 5 | ||||||||||||||||||
617 | - | |||||||||||||||||||
618 | priv->parseHttpResponse(d->reply->header(), true); | - | ||||||||||||||||||
619 | - | |||||||||||||||||||
620 | if (priv->phase == QAuthenticatorPrivate::Invalid) {
| 2-174 | ||||||||||||||||||
621 | // problem parsing the reply | - | ||||||||||||||||||
622 | d->socket->close(); | - | ||||||||||||||||||
623 | setState(QAbstractSocket::UnconnectedState); | - | ||||||||||||||||||
624 | setError(QAbstractSocket::ProxyProtocolError, tr("Error parsing authentication request from proxy")); | - | ||||||||||||||||||
625 | emitConnectionNotification(); | - | ||||||||||||||||||
626 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||||||||||||||
627 | } | - | ||||||||||||||||||
628 | - | |||||||||||||||||||
629 | bool willClose; | - | ||||||||||||||||||
630 | QByteArray proxyConnectionHeader = d->reply->headerField("Proxy-Connection"); | - | ||||||||||||||||||
631 | // Although most proxies use the unofficial Proxy-Connection header, the Connection header | - | ||||||||||||||||||
632 | // from http spec is also allowed. | - | ||||||||||||||||||
633 | if (proxyConnectionHeader.isEmpty())
| 3-171 | ||||||||||||||||||
634 | proxyConnectionHeader = d->reply->headerField("Connection"); executed 3 times by 1 test: proxyConnectionHeader = d->reply->headerField("Connection"); Executed by:
| 3 | ||||||||||||||||||
635 | proxyConnectionHeader = proxyConnectionHeader.toLower(); | - | ||||||||||||||||||
636 | if (proxyConnectionHeader == "close") {
| 4-170 | ||||||||||||||||||
637 | willClose = true; | - | ||||||||||||||||||
638 | } else if (proxyConnectionHeader == "keep-alive") { executed 170 times by 7 tests: end of block Executed by:
| 1-170 | ||||||||||||||||||
639 | willClose = false; | - | ||||||||||||||||||
640 | } else { executed 1 time by 1 test: end of block Executed by:
| 1 | ||||||||||||||||||
641 | // no Proxy-Connection header, so use the default | - | ||||||||||||||||||
642 | // HTTP 1.1's default behaviour is to keep persistent connections | - | ||||||||||||||||||
643 | // HTTP 1.0 or earlier, so we expect the server to close | - | ||||||||||||||||||
644 | willClose = (d->reply->majorVersion() * 0x100 + d->reply->minorVersion()) <= 0x0100; | - | ||||||||||||||||||
645 | } executed 3 times by 1 test: end of block Executed by:
| 3 | ||||||||||||||||||
646 | - | |||||||||||||||||||
647 | if (willClose) {
| 1-173 | ||||||||||||||||||
648 | // the server will disconnect, so let's avoid receiving an error | - | ||||||||||||||||||
649 | // especially since the signal below may trigger a new event loop | - | ||||||||||||||||||
650 | d->socket->disconnectFromHost(); | - | ||||||||||||||||||
651 | d->socket->readAll(); | - | ||||||||||||||||||
652 | //We're done with the reply and need to reset it for the next connection | - | ||||||||||||||||||
653 | delete d->reply; | - | ||||||||||||||||||
654 | d->reply = new QHttpNetworkReply; | - | ||||||||||||||||||
655 | } executed 173 times by 7 tests: end of block Executed by:
| 173 | ||||||||||||||||||
656 | - | |||||||||||||||||||
657 | if (priv->phase == QAuthenticatorPrivate::Done)
| 3-171 | ||||||||||||||||||
658 | emit proxyAuthenticationRequired(d->proxy, &d->authenticator); executed 171 times by 7 tests: proxyAuthenticationRequired(d->proxy, &d->authenticator); Executed by:
| 171 | ||||||||||||||||||
659 | // priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above. | - | ||||||||||||||||||
660 | if (priv->phase == QAuthenticatorPrivate::Done) {
| 6-168 | ||||||||||||||||||
661 | setError(QAbstractSocket::ProxyAuthenticationRequiredError, tr("Authentication required")); | - | ||||||||||||||||||
662 | d->socket->disconnectFromHost(); | - | ||||||||||||||||||
663 | } else { executed 6 times by 3 tests: end of block Executed by:
| 6 | ||||||||||||||||||
664 | // close the connection if it isn't already and reconnect using the chosen authentication method | - | ||||||||||||||||||
665 | d->state = SendAuthentication; | - | ||||||||||||||||||
666 | if (willClose) {
| 1-167 | ||||||||||||||||||
667 | d->socket->connectToHost(d->proxy.hostName(), d->proxy.port()); | - | ||||||||||||||||||
668 | } else { executed 167 times by 7 tests: end of block Executed by:
| 167 | ||||||||||||||||||
669 | // send the HTTP CONNECT again | - | ||||||||||||||||||
670 | slotSocketConnected(); | - | ||||||||||||||||||
671 | } executed 1 time by 1 test: end of block Executed by:
| 1 | ||||||||||||||||||
672 | return; executed 168 times by 7 tests: return; Executed by:
| 168 | ||||||||||||||||||
673 | } | - | ||||||||||||||||||
674 | } else { | - | ||||||||||||||||||
675 | d->socket->close(); | - | ||||||||||||||||||
676 | setState(QAbstractSocket::UnconnectedState); | - | ||||||||||||||||||
677 | if (statusCode == 403 || statusCode == 405) {
| 2-19 | ||||||||||||||||||
678 | // 403 Forbidden | - | ||||||||||||||||||
679 | // 405 Method Not Allowed | - | ||||||||||||||||||
680 | setError(QAbstractSocket::SocketAccessError, tr("Proxy denied connection")); | - | ||||||||||||||||||
681 | } else if (statusCode == 404) { executed 5 times by 1 test: end of block Executed by:
| 5-10 | ||||||||||||||||||
682 | // 404 Not Found: host lookup error | - | ||||||||||||||||||
683 | setError(QAbstractSocket::HostNotFoundError, QAbstractSocket::tr("Host not found")); | - | ||||||||||||||||||
684 | } else if (statusCode == 503) { executed 10 times by 2 tests: end of block Executed by:
| 1-10 | ||||||||||||||||||
685 | // 503 Service Unavailable: Connection Refused | - | ||||||||||||||||||
686 | setError(QAbstractSocket::ConnectionRefusedError, QAbstractSocket::tr("Connection refused")); | - | ||||||||||||||||||
687 | } else { executed 6 times by 2 tests: end of block Executed by:
| 6 | ||||||||||||||||||
688 | // Some other reply | - | ||||||||||||||||||
689 | //qWarning("UNEXPECTED RESPONSE: [%s]", responseHeader.toString().toLatin1().data()); | - | ||||||||||||||||||
690 | setError(QAbstractSocket::ProxyProtocolError, tr("Error communicating with HTTP proxy")); | - | ||||||||||||||||||
691 | } executed 1 time by 1 test: end of block Executed by:
| 1 | ||||||||||||||||||
692 | } | - | ||||||||||||||||||
693 | - | |||||||||||||||||||
694 | // The handshake is done; notify that we're connected (or failed to connect) | - | ||||||||||||||||||
695 | emitConnectionNotification(); | - | ||||||||||||||||||
696 | } executed 340 times by 7 tests: end of block Executed by:
| 340 | ||||||||||||||||||
697 | - | |||||||||||||||||||
698 | bool QHttpSocketEngine::readHttpHeader() | - | ||||||||||||||||||
699 | { | - | ||||||||||||||||||
700 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
701 | - | |||||||||||||||||||
702 | if (d->state != ReadResponseHeader) | - | ||||||||||||||||||
703 | return false; | - | ||||||||||||||||||
704 | - | |||||||||||||||||||
705 | bool ok = true; | - | ||||||||||||||||||
706 | if (d->reply->d_func()->state == QHttpNetworkReplyPrivate::NothingDoneState) { | - | ||||||||||||||||||
707 | // do not keep old content sizes, status etc. around | - | ||||||||||||||||||
708 | d->reply->d_func()->clearHttpLayerInformation(); | - | ||||||||||||||||||
709 | d->reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; | - | ||||||||||||||||||
710 | } | - | ||||||||||||||||||
711 | if (d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingStatusState) { | - | ||||||||||||||||||
712 | ok = d->reply->d_func()->readStatus(d->socket) != -1; | - | ||||||||||||||||||
713 | if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingStatusState) | - | ||||||||||||||||||
714 | return true; //Not done parsing headers yet, wait for more data | - | ||||||||||||||||||
715 | } | - | ||||||||||||||||||
716 | if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingHeaderState) { | - | ||||||||||||||||||
717 | ok = d->reply->d_func()->readHeader(d->socket) != -1; | - | ||||||||||||||||||
718 | if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingHeaderState) | - | ||||||||||||||||||
719 | return true; //Not done parsing headers yet, wait for more data | - | ||||||||||||||||||
720 | } | - | ||||||||||||||||||
721 | if (ok) { | - | ||||||||||||||||||
722 | bool contentLengthOk; | - | ||||||||||||||||||
723 | int contentLength = d->reply->headerField("Content-Length").toInt(&contentLengthOk); | - | ||||||||||||||||||
724 | if (contentLengthOk && contentLength > 0) | - | ||||||||||||||||||
725 | d->pendingResponseData = contentLength; | - | ||||||||||||||||||
726 | d->state = ReadResponseContent; // we are done reading the header | - | ||||||||||||||||||
727 | } | - | ||||||||||||||||||
728 | return ok; | - | ||||||||||||||||||
729 | } | - | ||||||||||||||||||
730 | - | |||||||||||||||||||
731 | void QHttpSocketEngine::slotSocketBytesWritten() | - | ||||||||||||||||||
732 | { | - | ||||||||||||||||||
733 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
734 | if (d->state == Connected && d->writeNotificationEnabled) | - | ||||||||||||||||||
735 | emitWriteNotification(); | - | ||||||||||||||||||
736 | } | - | ||||||||||||||||||
737 | - | |||||||||||||||||||
738 | void QHttpSocketEngine::slotSocketError(QAbstractSocket::SocketError error) | - | ||||||||||||||||||
739 | { | - | ||||||||||||||||||
740 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
741 | - | |||||||||||||||||||
742 | if (d->state != Connected) { | - | ||||||||||||||||||
743 | // we are in proxy handshaking stages | - | ||||||||||||||||||
744 | if (error == QAbstractSocket::HostNotFoundError) | - | ||||||||||||||||||
745 | setError(QAbstractSocket::ProxyNotFoundError, tr("Proxy server not found")); | - | ||||||||||||||||||
746 | else if (error == QAbstractSocket::ConnectionRefusedError) | - | ||||||||||||||||||
747 | setError(QAbstractSocket::ProxyConnectionRefusedError, tr("Proxy connection refused")); | - | ||||||||||||||||||
748 | else if (error == QAbstractSocket::SocketTimeoutError) | - | ||||||||||||||||||
749 | setError(QAbstractSocket::ProxyConnectionTimeoutError, tr("Proxy server connection timed out")); | - | ||||||||||||||||||
750 | else if (error == QAbstractSocket::RemoteHostClosedError) | - | ||||||||||||||||||
751 | setError(QAbstractSocket::ProxyConnectionClosedError, tr("Proxy connection closed prematurely")); | - | ||||||||||||||||||
752 | else | - | ||||||||||||||||||
753 | setError(error, d->socket->errorString()); | - | ||||||||||||||||||
754 | emitConnectionNotification(); | - | ||||||||||||||||||
755 | return; | - | ||||||||||||||||||
756 | } | - | ||||||||||||||||||
757 | - | |||||||||||||||||||
758 | // We're connected | - | ||||||||||||||||||
759 | if (error == QAbstractSocket::SocketTimeoutError) | - | ||||||||||||||||||
760 | return; // ignore this error | - | ||||||||||||||||||
761 | - | |||||||||||||||||||
762 | d->state = None; | - | ||||||||||||||||||
763 | setError(error, d->socket->errorString()); | - | ||||||||||||||||||
764 | if (error != QAbstractSocket::RemoteHostClosedError) | - | ||||||||||||||||||
765 | qDebug() << "QHttpSocketEngine::slotSocketError: got weird error =" << error; | - | ||||||||||||||||||
766 | //read notification needs to always be emitted, otherwise the higher layer doesn't get the disconnected signal | - | ||||||||||||||||||
767 | emitReadNotification(); | - | ||||||||||||||||||
768 | } | - | ||||||||||||||||||
769 | - | |||||||||||||||||||
770 | void QHttpSocketEngine::slotSocketStateChanged(QAbstractSocket::SocketState state) | - | ||||||||||||||||||
771 | { | - | ||||||||||||||||||
772 | Q_UNUSED(state); | - | ||||||||||||||||||
773 | } | - | ||||||||||||||||||
774 | - | |||||||||||||||||||
775 | void QHttpSocketEngine::emitPendingReadNotification() | - | ||||||||||||||||||
776 | { | - | ||||||||||||||||||
777 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
778 | d->readNotificationPending = false; | - | ||||||||||||||||||
779 | if (d->readNotificationEnabled) | - | ||||||||||||||||||
780 | emit readNotification(); | - | ||||||||||||||||||
781 | } | - | ||||||||||||||||||
782 | - | |||||||||||||||||||
783 | void QHttpSocketEngine::emitPendingWriteNotification() | - | ||||||||||||||||||
784 | { | - | ||||||||||||||||||
785 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
786 | d->writeNotificationPending = false; | - | ||||||||||||||||||
787 | if (d->writeNotificationEnabled) | - | ||||||||||||||||||
788 | emit writeNotification(); | - | ||||||||||||||||||
789 | } | - | ||||||||||||||||||
790 | - | |||||||||||||||||||
791 | void QHttpSocketEngine::emitPendingConnectionNotification() | - | ||||||||||||||||||
792 | { | - | ||||||||||||||||||
793 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
794 | d->connectionNotificationPending = false; | - | ||||||||||||||||||
795 | emit connectionNotification(); | - | ||||||||||||||||||
796 | } | - | ||||||||||||||||||
797 | - | |||||||||||||||||||
798 | void QHttpSocketEngine::emitReadNotification() | - | ||||||||||||||||||
799 | { | - | ||||||||||||||||||
800 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
801 | d->readNotificationActivated = true;// if there is a connection notification pending we have to emit the readNotification | - | ||||||||||||||||||
802 | // incase there is connection error. This is only needed for Windows, but it does not | - | ||||||||||||||||||
803 | // hurt in other cases. | - | ||||||||||||||||||
804 | if ((d->readNotificationEnabled && !d->readNotificationPending) || d->connectionNotificationPending) {
| 13-3309 | ||||||||||||||||||
805 | d->readNotificationPending = true; | - | ||||||||||||||||||
806 | QMetaObject::invokeMethod(this, "emitPendingReadNotification", Qt::QueuedConnection); | - | ||||||||||||||||||
807 | } executed 3341 times by 7 tests: end of block Executed by:
| 3341 | ||||||||||||||||||
808 | } executed 3354 times by 7 tests: end of block Executed by:
| 3354 | ||||||||||||||||||
809 | - | |||||||||||||||||||
810 | void QHttpSocketEngine::emitWriteNotification() | - | ||||||||||||||||||
811 | { | - | ||||||||||||||||||
812 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
813 | d->writeNotificationActivated = true;if (d->writeNotificationEnabled && !d->writeNotificationPending) {
| 0-390 | ||||||||||||||||||
814 | d->writeNotificationPending = true; | - | ||||||||||||||||||
815 | QMetaObject::invokeMethod(this, "emitPendingWriteNotification", Qt::QueuedConnection); | - | ||||||||||||||||||
816 | } executed 264 times by 7 tests: end of block Executed by:
| 264 | ||||||||||||||||||
817 | } executed 390 times by 7 tests: end of block Executed by:
| 390 | ||||||||||||||||||
818 | - | |||||||||||||||||||
819 | void QHttpSocketEngine::emitConnectionNotification() | - | ||||||||||||||||||
820 | { | - | ||||||||||||||||||
821 | Q_D(QHttpSocketEngine); | - | ||||||||||||||||||
822 | if (!d->connectionNotificationPending) { | - | ||||||||||||||||||
823 | d->connectionNotificationPending = true; | - | ||||||||||||||||||
824 | QMetaObject::invokeMethod(this, "emitPendingConnectionNotification", Qt::QueuedConnection); | - | ||||||||||||||||||
825 | } | - | ||||||||||||||||||
826 | } | - | ||||||||||||||||||
827 | - | |||||||||||||||||||
828 | QHttpSocketEnginePrivate::QHttpSocketEnginePrivate() | - | ||||||||||||||||||
829 | : readNotificationEnabled(false) | - | ||||||||||||||||||
830 | , writeNotificationEnabled(false) | - | ||||||||||||||||||
831 | , exceptNotificationEnabled(false) | - | ||||||||||||||||||
, readNotificationActivated(false) | ||||||||||||||||||||
, writeNotificationActivated(false) | ||||||||||||||||||||
832 | , readNotificationPending(false) | - | ||||||||||||||||||
833 | , writeNotificationPending(false) | - | ||||||||||||||||||
834 | , connectionNotificationPending(false) | - | ||||||||||||||||||
835 | , credentialsSent(false) | - | ||||||||||||||||||
836 | , pendingResponseData(0) | - | ||||||||||||||||||
837 | { | - | ||||||||||||||||||
838 | socket = 0; | - | ||||||||||||||||||
839 | reply = 0; | - | ||||||||||||||||||
840 | state = QHttpSocketEngine::None; | - | ||||||||||||||||||
841 | } executed 375 times by 7 tests: end of block Executed by:
| 375 | ||||||||||||||||||
842 | - | |||||||||||||||||||
843 | QHttpSocketEnginePrivate::~QHttpSocketEnginePrivate() | - | ||||||||||||||||||
844 | { | - | ||||||||||||||||||
845 | } | - | ||||||||||||||||||
846 | - | |||||||||||||||||||
847 | QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socketType, | - | ||||||||||||||||||
848 | const QNetworkProxy &proxy, | - | ||||||||||||||||||
849 | QObject *parent) | - | ||||||||||||||||||
850 | { | - | ||||||||||||||||||
851 | if (socketType != QAbstractSocket::TcpSocket) | - | ||||||||||||||||||
852 | return 0; | - | ||||||||||||||||||
853 | - | |||||||||||||||||||
854 | // proxy type must have been resolved by now | - | ||||||||||||||||||
855 | if (proxy.type() != QNetworkProxy::HttpProxy) | - | ||||||||||||||||||
856 | return 0; | - | ||||||||||||||||||
857 | - | |||||||||||||||||||
858 | // we only accept active sockets | - | ||||||||||||||||||
859 | if (!qobject_cast<QAbstractSocket *>(parent)) | - | ||||||||||||||||||
860 | return 0; | - | ||||||||||||||||||
861 | - | |||||||||||||||||||
862 | QHttpSocketEngine *engine = new QHttpSocketEngine(parent); | - | ||||||||||||||||||
863 | engine->setProxy(proxy); | - | ||||||||||||||||||
864 | return engine; | - | ||||||||||||||||||
865 | } | - | ||||||||||||||||||
866 | - | |||||||||||||||||||
867 | QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(qintptr, QObject *) | - | ||||||||||||||||||
868 | { | - | ||||||||||||||||||
869 | return 0; | - | ||||||||||||||||||
870 | } | - | ||||||||||||||||||
871 | - | |||||||||||||||||||
872 | QT_END_NAMESPACE | - | ||||||||||||||||||
873 | - | |||||||||||||||||||
874 | #endif | - | ||||||||||||||||||
Source code | Switch to Preprocessed file |