source: trunk/src/network/access/qnetworkaccessbackend.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 10.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qnetworkaccessbackend_p.h"
43#include "qnetworkaccessmanager_p.h"
44#include "qnetworkrequest.h"
45#include "qnetworkreply.h"
46#include "qnetworkreply_p.h"
47#include "QtCore/qhash.h"
48#include "QtCore/qmutex.h"
49#include "QtNetwork/qnetworksession.h"
50
51#include "qnetworkaccesscachebackend_p.h"
52#include "qabstractnetworkcache.h"
53#include "qhostinfo.h"
54
55#include "private/qnoncontiguousbytedevice_p.h"
56
57QT_BEGIN_NAMESPACE
58
59static bool factoryDataShutdown = false;
60class QNetworkAccessBackendFactoryData: public QList<QNetworkAccessBackendFactory *>
61{
62public:
63 QNetworkAccessBackendFactoryData() : mutex(QMutex::Recursive) { }
64 ~QNetworkAccessBackendFactoryData()
65 {
66 QMutexLocker locker(&mutex); // why do we need to lock?
67 factoryDataShutdown = true;
68 }
69
70 QMutex mutex;
71};
72Q_GLOBAL_STATIC(QNetworkAccessBackendFactoryData, factoryData)
73
74QNetworkAccessBackendFactory::QNetworkAccessBackendFactory()
75{
76 QMutexLocker locker(&factoryData()->mutex);
77 factoryData()->append(this);
78}
79
80QNetworkAccessBackendFactory::~QNetworkAccessBackendFactory()
81{
82 if (!factoryDataShutdown) {
83 QMutexLocker locker(&factoryData()->mutex);
84 factoryData()->removeAll(this);
85 }
86}
87
88QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessManager::Operation op,
89 const QNetworkRequest &request)
90{
91 if (!factoryDataShutdown) {
92 QMutexLocker locker(&factoryData()->mutex);
93 QNetworkAccessBackendFactoryData::ConstIterator it = factoryData()->constBegin(),
94 end = factoryData()->constEnd();
95 while (it != end) {
96 QNetworkAccessBackend *backend = (*it)->create(op, request);
97 if (backend) {
98 backend->manager = this;
99 return backend; // found a factory that handled our request
100 }
101 ++it;
102 }
103 }
104 return 0;
105}
106
107QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
108{
109 QNonContiguousByteDevice* device = 0;
110
111 if (reply->outgoingDataBuffer)
112 device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer);
113 else if (reply->outgoingData) {
114 device = QNonContiguousByteDeviceFactory::create(reply->outgoingData);
115 } else {
116 return 0;
117 }
118
119 bool bufferDisallowed =
120 reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
121 QVariant(false)) == QVariant(true);
122 if (bufferDisallowed)
123 device->disableReset();
124
125 // make sure we delete this later
126 device->setParent(this);
127
128 connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64)));
129
130 return device;
131}
132
133// need to have this function since the reply is a private member variable
134// and the special backends need to access this.
135void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
136{
137 if (reply->isFinished())
138 return;
139 reply->emitUploadProgress(bytesSent, bytesTotal);
140}
141
142QNetworkAccessBackend::QNetworkAccessBackend()
143 : manager(0)
144 , reply(0)
145 , synchronous(false)
146{
147}
148
149QNetworkAccessBackend::~QNetworkAccessBackend()
150{
151}
152
153void QNetworkAccessBackend::downstreamReadyWrite()
154{
155 // do nothing
156}
157
158void QNetworkAccessBackend::setDownstreamLimited(bool b)
159{
160 Q_UNUSED(b);
161 // do nothing
162}
163
164void QNetworkAccessBackend::copyFinished(QIODevice *)
165{
166 // do nothing
167}
168
169void QNetworkAccessBackend::ignoreSslErrors()
170{
171 // do nothing
172}
173
174void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors)
175{
176 Q_UNUSED(errors);
177 // do nothing
178}
179
180void QNetworkAccessBackend::fetchSslConfiguration(QSslConfiguration &) const
181{
182 // do nothing
183}
184
185void QNetworkAccessBackend::setSslConfiguration(const QSslConfiguration &)
186{
187 // do nothing
188}
189
190QNetworkCacheMetaData QNetworkAccessBackend::fetchCacheMetaData(const QNetworkCacheMetaData &) const
191{
192 return QNetworkCacheMetaData();
193}
194
195QNetworkAccessManager::Operation QNetworkAccessBackend::operation() const
196{
197 return reply->operation;
198}
199
200QNetworkRequest QNetworkAccessBackend::request() const
201{
202 return reply->request;
203}
204
205#ifndef QT_NO_NETWORKPROXY
206QList<QNetworkProxy> QNetworkAccessBackend::proxyList() const
207{
208 return reply->proxyList;
209}
210#endif
211
212QAbstractNetworkCache *QNetworkAccessBackend::networkCache() const
213{
214 if (!manager)
215 return 0;
216 return manager->networkCache;
217}
218
219void QNetworkAccessBackend::setCachingEnabled(bool enable)
220{
221 reply->setCachingEnabled(enable);
222}
223
224bool QNetworkAccessBackend::isCachingEnabled() const
225{
226 return reply->isCachingEnabled();
227}
228
229qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const
230{
231 return reply->nextDownstreamBlockSize();
232}
233
234void QNetworkAccessBackend::writeDownstreamData(QByteDataBuffer &list)
235{
236 reply->appendDownstreamData(list);
237}
238
239void QNetworkAccessBackend::writeDownstreamData(QIODevice *data)
240{
241 reply->appendDownstreamData(data);
242}
243
244QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const
245{
246 return reply->q_func()->header(header);
247}
248
249void QNetworkAccessBackend::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
250{
251 reply->setCookedHeader(header, value);
252}
253
254bool QNetworkAccessBackend::hasRawHeader(const QByteArray &headerName) const
255{
256 return reply->q_func()->hasRawHeader(headerName);
257}
258
259QByteArray QNetworkAccessBackend::rawHeader(const QByteArray &headerName) const
260{
261 return reply->q_func()->rawHeader(headerName);
262}
263
264QList<QByteArray> QNetworkAccessBackend::rawHeaderList() const
265{
266 return reply->q_func()->rawHeaderList();
267}
268
269void QNetworkAccessBackend::setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
270{
271 reply->setRawHeader(headerName, headerValue);
272}
273
274QVariant QNetworkAccessBackend::attribute(QNetworkRequest::Attribute code) const
275{
276 return reply->q_func()->attribute(code);
277}
278
279void QNetworkAccessBackend::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
280{
281 if (value.isValid())
282 reply->attributes.insert(code, value);
283 else
284 reply->attributes.remove(code);
285}
286QUrl QNetworkAccessBackend::url() const
287{
288 return reply->url;
289}
290
291void QNetworkAccessBackend::setUrl(const QUrl &url)
292{
293 reply->url = url;
294}
295
296void QNetworkAccessBackend::finished()
297{
298 reply->finished();
299}
300
301void QNetworkAccessBackend::error(QNetworkReply::NetworkError code, const QString &errorString)
302{
303 reply->error(code, errorString);
304}
305
306#ifndef QT_NO_NETWORKPROXY
307void QNetworkAccessBackend::proxyAuthenticationRequired(const QNetworkProxy &proxy,
308 QAuthenticator *authenticator)
309{
310 manager->proxyAuthenticationRequired(this, proxy, authenticator);
311}
312#endif
313
314void QNetworkAccessBackend::authenticationRequired(QAuthenticator *authenticator)
315{
316 manager->authenticationRequired(this, authenticator);
317}
318
319void QNetworkAccessBackend::cacheCredentials(QAuthenticator *authenticator)
320{
321 manager->cacheCredentials(this->reply->url, authenticator);
322}
323
324void QNetworkAccessBackend::metaDataChanged()
325{
326 reply->metaDataChanged();
327}
328
329void QNetworkAccessBackend::redirectionRequested(const QUrl &target)
330{
331 reply->redirectionRequested(target);
332}
333
334void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
335{
336#ifndef QT_NO_OPENSSL
337 reply->sslErrors(errors);
338#else
339 Q_UNUSED(errors);
340#endif
341}
342
343#ifndef QT_NO_BEARERMANAGEMENT
344
345/*!
346 Starts the backend. Returns true if the backend is started. Returns false if the backend
347 could not be started due to an unopened or roaming session. The caller should recall this
348 function once the session has been opened or the roaming process has finished.
349*/
350bool QNetworkAccessBackend::start()
351{
352 if (!manager->networkSession) {
353 open();
354 return true;
355 }
356
357 // This is not ideal.
358 const QString host = reply->url.host();
359 if (host == QLatin1String("localhost") ||
360 QHostAddress(host) == QHostAddress::LocalHost ||
361 QHostAddress(host) == QHostAddress::LocalHostIPv6) {
362 // Don't need an open session for localhost access.
363 open();
364 return true;
365 }
366
367 if (manager->networkSession->isOpen() &&
368 manager->networkSession->state() == QNetworkSession::Connected) {
369 open();
370 return true;
371 }
372
373 return false;
374}
375#endif
376
377QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.