Changeset 769 for trunk/src/network/access
- Timestamp:
- Aug 2, 2010, 9:27:30 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.6.3 (added) merged: 768 /branches/vendor/nokia/qt/current merged: 767 /branches/vendor/nokia/qt/4.6.2 removed
- Property svn:mergeinfo changed
-
trunk/src/network/access/qfilenetworkreply.cpp
r651 r769 50 50 51 51 QFileNetworkReplyPrivate::QFileNetworkReplyPrivate() 52 : QNetworkReplyPrivate(), realFileSize(0) 53 { 52 : QNetworkReplyPrivate(), fileEngine(0), fileSize(0), filePos(0) 53 { 54 } 55 56 QFileNetworkReplyPrivate::~QFileNetworkReplyPrivate() 57 { 58 delete fileEngine; 54 59 } 55 60 … … 95 100 fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery); 96 101 } 97 d->realFile.setFileName(fileName); 98 99 QFileInfo fi(d->realFile); 102 103 QFileInfo fi(fileName); 100 104 if (fi.isDir()) { 101 105 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); … … 107 111 } 108 112 109 bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); 113 d->fileEngine = QAbstractFileEngine::create(fileName); 114 bool opened = d->fileEngine->open(QIODevice::ReadOnly | QIODevice::Unbuffered); 110 115 111 116 // could we open the file? 112 117 if (!opened) { 113 118 QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") 114 .arg( d->realFile.fileName(), d->realFile.errorString());115 116 if ( d->realFile.exists()) {119 .arg(fileName, d->fileEngine->errorString()); 120 121 if (fi.exists()) { 117 122 setError(QNetworkReply::ContentAccessDenied, msg); 118 123 QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, … … 127 132 } 128 133 129 d-> realFileSize = fi.size();134 d->fileSize = fi.size(); 130 135 setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); 131 setHeader(QNetworkRequest::ContentLengthHeader, d-> realFileSize);136 setHeader(QNetworkRequest::ContentLengthHeader, d->fileSize); 132 137 133 138 QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); 134 139 QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, 135 Q_ARG(qint64, d-> realFileSize), Q_ARG(qint64, d->realFileSize));140 Q_ARG(qint64, d->fileSize), Q_ARG(qint64, d->fileSize)); 136 141 QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); 137 142 QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); … … 147 152 Q_D(QFileNetworkReply); 148 153 QNetworkReply::close(); 149 d->realFile.close(); 154 if (d->fileEngine) 155 d->fileEngine->close(); 150 156 } 151 157 … … 154 160 Q_D(QFileNetworkReply); 155 161 QNetworkReply::close(); 156 d->realFile.close(); 162 if (d->fileEngine) 163 d->fileEngine->close(); 157 164 } 158 165 … … 160 167 { 161 168 Q_D(const QFileNetworkReply); 162 return QNetworkReply::bytesAvailable() + d->realFile.bytesAvailable(); 169 if (!d->fileEngine) 170 return 0; 171 172 return QNetworkReply::bytesAvailable() + d->fileSize - d->filePos; 163 173 } 164 174 … … 171 181 { 172 182 Q_D(const QFileNetworkReply); 173 return d-> realFileSize;183 return d->fileSize; 174 184 } 175 185 … … 180 190 { 181 191 Q_D(QFileNetworkReply); 182 qint64 ret = d->realFile.read(data, maxlen); 183 if (ret == 0 && bytesAvailable() == 0) 192 if (!d->fileEngine) 193 return -1; 194 195 qint64 ret = d->fileEngine->read(data, maxlen); 196 if (ret == 0 && bytesAvailable() == 0) { 184 197 return -1; // everything had been read 185 else 186 return ret; 198 } else if (ret > 0) { 199 d->filePos += ret; 200 } 201 202 return ret; 187 203 } 188 204 -
trunk/src/network/access/qfilenetworkreply_p.h
r651 r769 58 58 #include "qnetworkaccessmanager.h" 59 59 #include <QFile> 60 #include <QAbstractFileEngine> 60 61 61 62 QT_BEGIN_NAMESPACE … … 86 87 public: 87 88 QFileNetworkReplyPrivate(); 89 ~QFileNetworkReplyPrivate(); 88 90 89 QFile realFile; 90 qint64 realFileSize; 91 QAbstractFileEngine *fileEngine; 92 qint64 fileSize; 93 qint64 filePos; 91 94 92 95 virtual bool isFinished() const; -
trunk/src/network/access/qftp.cpp
r651 r769 2310 2310 { 2311 2311 Q_Q(QFtp); 2312 2313 if (pending.isEmpty()) { 2314 qWarning() << "QFtpPrivate::_q_piError was called without pending command!"; 2315 return; 2316 } 2317 2312 2318 QFtpCommand *c = pending.first(); 2313 2319 -
trunk/src/network/access/qhttpnetworkconnection.cpp
r651 r769 72 72 #endif 73 73 74 // the maximum amount of requests that might be pipelined into a socket 75 // from what was suggested, 3 seems to be OK 74 // The pipeline length. So there will be 4 requests in flight. 76 75 const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; 76 // Only re-fill the pipeline if there's defaultRePipelineLength slots free in the pipeline. 77 // This means that there are 2 requests in flight and 2 slots free that will be re-filled. 78 const int QHttpNetworkConnectionPrivate::defaultRePipelineLength = 2; 77 79 78 80 … … 405 407 reply->setRequest(request); 406 408 reply->d_func()->connection = q; 409 reply->d_func()->connectionChannel = &channels[0]; // will have the correct one set later 407 410 HttpMessagePair pair = qMakePair(request, reply); 408 411 … … 416 419 break; 417 420 } 421 418 422 // this used to be called via invokeMethod and a QueuedConnection 423 // It is the only place _q_startNextRequest is called directly without going 424 // through the event loop using a QueuedConnection. 425 // This is dangerous because of recursion that might occur when emitting 426 // signals as DirectConnection from this code path. Therefore all signal 427 // emissions that can come out from this code path need to 428 // be QueuedConnection. 429 // We are currently trying to fine-tune this. 419 430 _q_startNextRequest(); 431 432 420 433 return reply; 421 434 } … … 423 436 void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) 424 437 { 438 Q_Q(QHttpNetworkConnection); 439 425 440 QHttpNetworkRequest request = pair.first; 426 441 switch (request.priority()) { … … 433 448 break; 434 449 } 435 // this used to be called via invokeMethod and a QueuedConnection 436 _q_startNextRequest();450 451 QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); 437 452 } 438 453 … … 475 490 int i = indexOf(socket); 476 491 477 bool highPriorityQueueProcessingDone = false; 478 bool lowPriorityQueueProcessingDone = false; 479 480 while (!highPriorityQueueProcessingDone && !lowPriorityQueueProcessingDone) { 481 // this loop runs once per request we intend to pipeline in. 482 483 if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported) 484 return; 485 486 // the current request that is in must already support pipelining 487 if (!channels[i].request.isPipeliningAllowed()) 488 return; 489 490 // the current request must be a idempotent (right now we only check GET) 491 if (channels[i].request.operation() != QHttpNetworkRequest::Get) 492 return; 493 494 // check if socket is connected 495 if (socket->state() != QAbstractSocket::ConnectedState) 496 return; 497 498 // check for resendCurrent 499 if (channels[i].resendCurrent) 500 return; 501 502 // we do not like authentication stuff 503 // ### make sure to be OK with this in later releases 504 if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) 505 return; 506 if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) 507 return; 508 509 // check for pipeline length 492 // return fast if there was no reply right now processed 493 if (channels[i].reply == 0) 494 return; 495 496 if (! (defaultPipelineLength - channels[i].alreadyPipelinedRequests.length() >= defaultRePipelineLength)) { 497 return; 498 } 499 500 if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported) 501 return; 502 503 // the current request that is in must already support pipelining 504 if (!channels[i].request.isPipeliningAllowed()) 505 return; 506 507 // the current request must be a idempotent (right now we only check GET) 508 if (channels[i].request.operation() != QHttpNetworkRequest::Get) 509 return; 510 511 // check if socket is connected 512 if (socket->state() != QAbstractSocket::ConnectedState) 513 return; 514 515 // check for resendCurrent 516 if (channels[i].resendCurrent) 517 return; 518 519 // we do not like authentication stuff 520 // ### make sure to be OK with this in later releases 521 if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) 522 return; 523 if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) 524 return; 525 526 // must be in ReadingState or WaitingState 527 if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState 528 || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) 529 return; 530 531 532 //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing highPriorityQueue, size=" << highPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); 533 int lengthBefore; 534 while (!highPriorityQueue.isEmpty()) { 535 lengthBefore = channels[i].alreadyPipelinedRequests.length(); 536 fillPipeline(highPriorityQueue, channels[i]); 537 510 538 if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) 511 539 return; 512 540 513 // must be in ReadingState or WaitingState 514 if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState 515 || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) 541 if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) 542 break; // did not process anything, now do the low prio queue 543 } 544 545 //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing lowPriorityQueue, size=" << lowPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); 546 while (!lowPriorityQueue.isEmpty()) { 547 lengthBefore = channels[i].alreadyPipelinedRequests.length(); 548 fillPipeline(lowPriorityQueue, channels[i]); 549 550 if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) 516 551 return; 517 552 518 highPriorityQueueProcessingDone = fillPipeline(highPriorityQueue, channels[i]); 519 // not finished with highPriorityQueue? then loop again 520 if (!highPriorityQueueProcessingDone) 521 continue; 522 // highPriorityQueue was processed, now deal with the lowPriorityQueue 523 lowPriorityQueueProcessingDone = fillPipeline(lowPriorityQueue, channels[i]); 524 } 553 if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) 554 break; // did not process anything 555 } 556 557 525 558 } 526 559 … … 682 715 683 716 717 // This function must be called from the event loop. The only 718 // exception is documented in QHttpNetworkConnectionPrivate::queueRequest 719 // although it is called _q_startNextRequest, it will actually start multiple requests when possible 684 720 void QHttpNetworkConnectionPrivate::_q_startNextRequest() 685 721 { … … 689 725 channels[i].resendCurrent = false; 690 726 channels[i].state = QHttpNetworkConnectionChannel::IdleState; 691 if (channels[i].reply) 692 channels[i].sendRequest(); 727 728 // if this is not possible, error will be emitted and connection terminated 729 if (!channels[i].resetUploadData()) 730 continue; 731 channels[i].sendRequest(); 693 732 } 694 733 } … … 696 735 // dequeue new ones 697 736 698 QAbstractSocket *socket = 0; 737 // return fast if there is nothing to do 738 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) 739 return; 740 // try to get a free AND connected socket 699 741 for (int i = 0; i < channelCount; ++i) { 700 QAbstractSocket *chSocket = channels[i].socket;701 // try to get a free AND connected socket702 742 if (!channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { 703 socket = chSocket; 704 dequeueAndSendRequest(socket); 705 break; 706 } 707 } 708 709 if (!socket) { 710 for (int i = 0; i < channelCount; ++i) { 711 QAbstractSocket *chSocket = channels[i].socket; 712 // try to get a free unconnected socket 713 if (!channels[i].isSocketBusy()) { 714 socket = chSocket; 715 dequeueAndSendRequest(socket); 716 break; 717 } 743 dequeueAndSendRequest(channels[i].socket); 744 } 745 } 746 747 // return fast if there is nothing to do 748 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) 749 return; 750 // try to get a free unconnected socket 751 for (int i = 0; i < channelCount; ++i) { 752 if (!channels[i].isSocketBusy()) { 753 dequeueAndSendRequest(channels[i].socket); 718 754 } 719 755 } … … 729 765 if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) 730 766 return; 731 for (int j = 0; j < channelCount; j++) 732 fillPipeline(channels[j].socket); 767 for (int i = 0; i < channelCount; i++) 768 if (channels[i].socket->state() == QAbstractSocket::ConnectedState) 769 fillPipeline(channels[i].socket); 733 770 } 734 771 … … 856 893 // SSL support below 857 894 #ifndef QT_NO_OPENSSL 858 QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNetworkReply &reply) const859 {860 if (!encrypt)861 return QSslConfiguration();862 863 for (int i = 0; i < channelCount; ++i)864 if (channels[i].reply == &reply)865 return static_cast<QSslSocket *>(channels[0].socket)->sslConfiguration();866 return QSslConfiguration(); // pending or done request867 }868 869 895 void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config) 870 896 { -
trunk/src/network/access/qhttpnetworkconnection_p.h
r651 r769 157 157 static const int defaultChannelCount; 158 158 static const int defaultPipelineLength; 159 static const int defaultRePipelineLength; 159 160 160 161 QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); … … 211 212 bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend); 212 213 213 214 #ifndef QT_NO_OPENSSL215 QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const;216 #endif217 218 214 #ifndef QT_NO_NETWORKPROXY 219 215 QNetworkProxy networkProxy; -
trunk/src/network/access/qhttpnetworkconnectionchannel.cpp
r651 r769 59 59 // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp 60 60 61 QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() 62 : socket(0) 63 , state(IdleState) 64 , reply(0) 65 , written(0) 66 , bytesTotal(0) 67 , resendCurrent(false) 68 , lastStatus(0) 69 , pendingEncrypt(false) 70 , reconnectAttempts(2) 71 , authMehtod(QAuthenticatorPrivate::None) 72 , proxyAuthMehtod(QAuthenticatorPrivate::None) 73 #ifndef QT_NO_OPENSSL 74 , ignoreAllSslErrors(false) 75 #endif 76 , pipeliningSupported(PipeliningSupportUnknown) 77 , connection(0) 78 { 79 // Inlining this function in the header leads to compiler error on 80 // release-armv5, on at least timebox 9.2 and 10.1. 81 } 82 61 83 void QHttpNetworkConnectionChannel::init() 62 84 { … … 125 147 bool QHttpNetworkConnectionChannel::sendRequest() 126 148 { 149 if (!reply) { 150 // heh, how should that happen! 151 qWarning() << "QHttpNetworkConnectionChannel::sendRequest() called without QHttpNetworkReply"; 152 state = QHttpNetworkConnectionChannel::IdleState; 153 return false; 154 } 155 127 156 switch (state) { 128 157 case QHttpNetworkConnectionChannel::IdleState: { // write the header … … 135 164 written = 0; // excluding the header 136 165 bytesTotal = 0; 137 if (reply) { 138 139 140 reply->d_func()->autoDecompress = request.d->autoDecompress;141 reply->d_func()->pipeliningUsed = false;142 }143 state = QHttpNetworkConnectionChannel::WritingState; 166 167 reply->d_func()->clear(); 168 reply->d_func()->connection = connection; 169 reply->d_func()->connectionChannel = this; 170 reply->d_func()->autoDecompress = request.d->autoDecompress; 171 reply->d_func()->pipeliningUsed = false; 172 144 173 pendingEncrypt = false; 145 174 // if the url contains authentication parameters, use the new ones … … 175 204 176 205 bytesTotal = request.contentLength(); 206 207 state = QHttpNetworkConnectionChannel::WritingState; // start writing data 208 sendRequest(); //recurse 177 209 } else { 178 state = QHttpNetworkConnectionChannel::WaitingState; 179 sendRequest(); 180 break; 181 } 182 // write the initial chunk together with the headers 183 // fall through 210 state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response 211 sendRequest(); //recurse 212 } 213 214 break; 184 215 } 185 216 case QHttpNetworkConnectionChannel::WritingState: … … 191 222 emit reply->dataSendProgress(written, bytesTotal); 192 223 state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response 193 sendRequest(); 224 sendRequest(); // recurse 194 225 break; 195 226 } … … 255 286 256 287 // HTTP pipelining 257 connection->d_func()->fillPipeline(socket);258 socket->flush();288 //connection->d_func()->fillPipeline(socket); 289 //socket->flush(); 259 290 260 291 // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called 261 292 // this is needed if the sends an reply before we have finished sending the request. In that 262 293 // case receiveReply had been called before but ignored the server reply 263 QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); 294 if (socket->bytesAvailable()) 295 QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); 264 296 break; 265 297 } … … 279 311 Q_ASSERT(socket); 280 312 313 if (!reply) { 314 // heh, how should that happen! 315 qWarning() << "QHttpNetworkConnectionChannel::_q_receiveReply() called without QHttpNetworkReply," 316 << socket->bytesAvailable() << "bytes on socket."; 317 close(); 318 return; 319 } 320 321 // only run when the QHttpNetworkConnection is not currently being destructed, e.g. 322 // this function is called from _q_disconnected which is called because 323 // of ~QHttpNetworkConnectionPrivate 324 if (!qobject_cast<QHttpNetworkConnection*>(connection)) { 325 return; 326 } 327 281 328 qint64 bytes = 0; 282 329 QAbstractSocket::SocketState socketState = socket->state(); … … 284 331 // connection might be closed to signal the end of data 285 332 if (socketState == QAbstractSocket::UnconnectedState) { 286 if (!socket->bytesAvailable()) { 287 if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { 333 if (socket->bytesAvailable() <= 0) { 334 if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { 335 // finish this reply. this case happens when the server did not send a content length 288 336 reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; 289 this->state = QHttpNetworkConnectionChannel::IdleState;290 337 allDone(); 338 return; 291 339 } else { 292 // try to reconnect/resend before sending an error. 293 if (reconnectAttempts-- > 0) { 294 closeAndResendCurrentRequest(); 295 } else if (reply) { 296 reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); 297 emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); 298 QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); 299 } 300 } 340 handleUnexpectedEOF(); 341 return; 342 } 343 } else { 344 // socket not connected but still bytes for reading.. just continue in this function 301 345 } 302 346 } … … 304 348 // read loop for the response 305 349 while (socket->bytesAvailable()) { 306 QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;350 QHttpNetworkReplyPrivate::ReplyState state = reply->d_func()->state; 307 351 switch (state) { 308 case QHttpNetworkReplyPrivate::NothingDoneState: 352 case QHttpNetworkReplyPrivate::NothingDoneState: { 353 // only eat whitespace on the first call 354 eatWhitespace(); 355 state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; 356 // fallthrough 357 } 309 358 case QHttpNetworkReplyPrivate::ReadingStatusState: { 310 eatWhitespace();311 359 qint64 statusBytes = reply->d_func()->readStatus(socket); 312 if (statusBytes == -1 && reconnectAttempts <= 0) { 313 // too many errors reading/receiving/parsing the status, close the socket and emit error 314 close(); 315 reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::ProtocolFailure, socket); 316 emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); 317 QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); 318 break; 319 } else if (statusBytes == -1) { 320 reconnectAttempts--; 321 reply->d_func()->clear(); 322 closeAndResendCurrentRequest(); 323 break; 360 if (statusBytes == -1) { 361 // connection broke while reading status. also handled if later _q_disconnected is called 362 handleUnexpectedEOF(); 363 return; 324 364 } 325 365 bytes += statusBytes; … … 329 369 case QHttpNetworkReplyPrivate::ReadingHeaderState: { 330 370 QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); 331 bytes += replyPrivate->readHeader(socket); 371 qint64 headerBytes = replyPrivate->readHeader(socket); 372 if (headerBytes == -1) { 373 // connection broke while reading headers. also handled if later _q_disconnected is called 374 handleUnexpectedEOF(); 375 return; 376 } 377 bytes += headerBytes; 332 378 if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { 333 379 if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { … … 338 384 } 339 385 if (replyPrivate->statusCode == 100) { 386 replyPrivate->clearHttpLayerInformation(); 340 387 replyPrivate->state = QHttpNetworkReplyPrivate::ReadingStatusState; 341 388 break; // ignore … … 345 392 if (!replyPrivate->expectContent()) { 346 393 replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; 347 this->state = QHttpNetworkConnectionChannel::IdleState;348 394 allDone(); 349 return;395 break; 350 396 } 351 397 } … … 417 463 } 418 464 } 465 // still in ReadingDataState? This function will be called again by the socket's readyRead 419 466 if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) 420 467 break; 468 421 469 // everything done, fall through 422 470 } 423 471 case QHttpNetworkReplyPrivate::AllDoneState: 424 this->state = QHttpNetworkConnectionChannel::IdleState;425 472 allDone(); 426 473 break; … … 428 475 break; 429 476 } 477 } 478 } 479 480 // called when unexpectedly reading a -1 or when data is expected but socket is closed 481 void QHttpNetworkConnectionChannel::handleUnexpectedEOF() 482 { 483 if (reconnectAttempts <= 0) { 484 // too many errors reading/receiving/parsing the status, close the socket and emit error 485 requeueCurrentlyPipelinedRequests(); 486 close(); 487 reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); 488 emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); 489 QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); 490 } else { 491 reconnectAttempts--; 492 reply->d_func()->clear(); 493 reply->d_func()->connection = connection; 494 reply->d_func()->connectionChannel = this; 495 closeAndResendCurrentRequest(); 430 496 } 431 497 } … … 557 623 // ### at this point there should be no more data on the socket 558 624 // close if server requested 559 if (reply->d_func()->isConnectionCloseEnabled()) 625 bool connectionCloseEnabled = reply->d_func()->isConnectionCloseEnabled(); 626 if (connectionCloseEnabled) 560 627 close(); 561 628 // queue the finished signal, this is required since we might send new requests from … … 570 637 detectPipeliningSupport(); 571 638 639 // now the channel can be seen as free/idle again, all signal emissions for the reply have been done 640 this->state = QHttpNetworkConnectionChannel::IdleState; 641 642 // if it does not need to be sent again we can set it to 0 643 // the previous code did not do that and we had problems with accidental re-sending of a 644 // finished request. 645 // Note that this may trigger a segfault at some other point. But then we can fix the underlying 646 // problem. 647 if (!resendCurrent) 648 reply = 0; 649 572 650 // move next from pipeline to current request 573 651 if (!alreadyPipelinedRequests.isEmpty()) { 574 if (resendCurrent || reply->d_func()->isConnectionCloseEnabled()|| socket->state() != QAbstractSocket::ConnectedState) {652 if (resendCurrent || connectionCloseEnabled || socket->state() != QAbstractSocket::ConnectedState) { 575 653 // move the pipelined ones back to the main queue 576 654 requeueCurrentlyPipelinedRequests(); … … 592 670 593 671 // continue reading 594 _q_receiveReply(); 672 //_q_receiveReply(); 673 // this was wrong, allDone gets called from that function anyway. 595 674 } 596 675 } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) { … … 608 687 { 609 688 // detect HTTP Pipelining support 610 QByteArray serverHeaderField = reply->headerField("Server");689 QByteArray serverHeaderField; 611 690 if ( 612 // check for broken servers in server reply header613 // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining614 (!serverHeaderField.contains("Microsoft-IIS/4."))615 && (!serverHeaderField.contains("Microsoft-IIS/5."))616 && (!serverHeaderField.contains("Netscape-Enterprise/3."))617 691 // check for HTTP/1.1 618 &&(reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)692 (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1) 619 693 // check for not having connection close 620 694 && (!reply->d_func()->isConnectionCloseEnabled()) 621 695 // check if it is still connected 622 696 && (socket->state() == QAbstractSocket::ConnectedState) 697 // check for broken servers in server reply header 698 // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining 699 && (serverHeaderField = reply->headerField("Server"), !serverHeaderField.contains("Microsoft-IIS/4.")) 700 && (!serverHeaderField.contains("Microsoft-IIS/5.")) 701 && (!serverHeaderField.contains("Netscape-Enterprise/3.")) 702 // this is adpoted from the knowledge of the Nokia 7.x browser team (DEF143319) 703 && (!serverHeaderField.contains("WebLogic")) 623 704 ) { 624 705 pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported; … … 635 716 alreadyPipelinedRequests.clear(); 636 717 637 QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); 718 // only run when the QHttpNetworkConnection is not currently being destructed, e.g. 719 // this function is called from _q_disconnected which is called because 720 // of ~QHttpNetworkConnectionPrivate 721 if (qobject_cast<QHttpNetworkConnection*>(connection)) 722 QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); 638 723 } 639 724 … … 675 760 if (connection->d_func()->handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) { 676 761 if (resend) { 677 QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); 678 if (uploadByteDevice) { 679 if (uploadByteDevice->reset()) { 680 written = 0; 681 } else { 682 connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError); 683 break; 684 } 685 } 762 if (!resetUploadData()) 763 break; 686 764 687 765 reply->d_func()->eraseData(); … … 713 791 } 714 792 793 bool QHttpNetworkConnectionChannel::resetUploadData() 794 { 795 QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); 796 if (!uploadByteDevice) 797 return true; 798 799 if (uploadByteDevice->reset()) { 800 written = 0; 801 return true; 802 } else { 803 connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError); 804 return false; 805 } 806 } 807 808 715 809 void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) 716 810 { … … 719 813 QHttpNetworkRequest &request = pair.first; 720 814 QHttpNetworkReply *reply = pair.second; 721 if (reply) { 722 reply->d_func()->clear(); 723 reply->d_func()->connection = connection; 724 reply->d_func()->autoDecompress = request.d->autoDecompress; 725 reply->d_func()->pipeliningUsed = true; 726 } 815 reply->d_func()->clear(); 816 reply->d_func()->connection = connection; 817 reply->d_func()->connectionChannel = this; 818 reply->d_func()->autoDecompress = request.d->autoDecompress; 819 reply->d_func()->pipeliningUsed = true; 727 820 728 821 #ifndef QT_NO_NETWORKPROXY … … 788 881 // read the available data before closing 789 882 if (isSocketWaiting() || isSocketReading()) { 790 state = QHttpNetworkConnectionChannel::ReadingState;791 if (reply)883 if (reply) { 884 state = QHttpNetworkConnectionChannel::ReadingState; 792 885 _q_receiveReply(); 886 } 793 887 } else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) { 794 888 // re-sending request because the socket was in ClosingState … … 805 899 { 806 900 // improve performance since we get the request sent by the kernel ASAP 807 socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); 901 //socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); 902 // We have this commented out now. It did not have the effect we wanted. If we want to 903 // do this properly, Qt has to combine multiple HTTP requests into one buffer 904 // and send this to the kernel in one syscall and then the kernel immediately sends 905 // it as one TCP packet because of TCP_NODELAY. 906 // However, this code is currently not in Qt, so we rely on the kernel combining 907 // the requests into one TCP packet. 908 808 909 // not sure yet if it helps, but it makes sense 809 910 socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1); … … 872 973 break; 873 974 } 874 QPointer<Q Object> that = connection;975 QPointer<QHttpNetworkConnection> that = connection; 875 976 QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString()); 876 977 if (send2Reply) { … … 927 1028 // otherwise we do nothing 928 1029 } 929 #endif 1030 1031 #endif 1032 1033 void QHttpNetworkConnectionChannel::setConnection(QHttpNetworkConnection *c) 1034 { 1035 // Inlining this function in the header leads to compiler error on 1036 // release-armv5, on at least timebox 9.2 and 10.1. 1037 connection = c; 1038 } 930 1039 931 1040 QT_END_NAMESPACE -
trunk/src/network/access/qhttpnetworkconnectionchannel_p.h
r651 r769 66 66 #include <private/qhttpnetworkreply_p.h> 67 67 68 #include <private/qhttpnetworkconnection_p.h> 68 69 69 70 #ifndef QT_NO_HTTP … … 81 82 class QHttpNetworkReply; 82 83 class QByteArray; 83 class QHttpNetworkConnection;84 84 85 85 #ifndef HttpMessagePair … … 128 128 129 129 130 QHttpNetworkConnectionChannel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), 131 lastStatus(0), pendingEncrypt(false), reconnectAttempts(2), 132 authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None) 133 #ifndef QT_NO_OPENSSL 134 , ignoreAllSslErrors(false) 135 #endif 136 , pipeliningSupported(PipeliningSupportUnknown) 137 , connection(0) 138 {} 139 140 void setConnection(QHttpNetworkConnection *c) {connection = c;} 141 QHttpNetworkConnection *connection; 130 QHttpNetworkConnectionChannel(); 131 132 void setConnection(QHttpNetworkConnection *c); 133 QPointer<QHttpNetworkConnection> connection; 142 134 143 135 void init(); … … 152 144 void handleStatus(); // called from allDone() 153 145 146 bool resetUploadData(); // return true if resetting worked or there is no upload data 147 154 148 void pipelineInto(HttpMessagePair &pair); 155 149 void requeueCurrentlyPipelinedRequests(); 156 150 void detectPipeliningSupport(); 157 151 152 void handleUnexpectedEOF(); 158 153 void closeAndResendCurrentRequest(); 159 154 … … 185 180 }; 186 181 187 188 189 182 QT_END_NAMESPACE 190 183 -
trunk/src/network/access/qhttpnetworkheader.cpp
r651 r769 81 81 QByteArray result; 82 82 bool first = true; 83 foreach ( QByteArrayvalue, allValues) {83 foreach (const QByteArray &value, allValues) { 84 84 if (!first) 85 85 result += ", "; -
trunk/src/network/access/qhttpnetworkreply.cpp
r651 r769 180 180 { 181 181 Q_D(QHttpNetworkReply); 182 if (d->responseData.bufferCount() == 0) 183 return QByteArray(); 184 182 185 // we'll take the last buffer, so schedule another read from http 183 186 if (d->downstreamLimited && d->responseData.bufferCount() == 1) … … 220 223 } 221 224 222 void QHttpNetworkReplyPrivate::clear ()225 void QHttpNetworkReplyPrivate::clearHttpLayerInformation() 223 226 { 224 227 state = NothingDoneState; … … 230 233 currentChunkRead = 0; 231 234 connectionCloseEnabled = true; 232 connection = 0;233 235 #ifndef QT_NO_COMPRESS 234 236 if (initInflate) … … 237 239 initInflate = false; 238 240 streamEnd = false; 241 fields.clear(); 242 } 243 244 // TODO: Isn't everything HTTP layer related? We don't need to set connection and connectionChannel to 0 at all 245 void QHttpNetworkReplyPrivate::clear() 246 { 247 connection = 0; 248 connectionChannel = 0; 239 249 autoDecompress = false; 240 fields.clear();250 clearHttpLayerInformation(); 241 251 } 242 252 … … 424 434 qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) 425 435 { 436 if (fragment.isEmpty()) { 437 // reserve bytes for the status line. This is better than always append() which reallocs the byte array 438 fragment.reserve(32); 439 } 440 426 441 qint64 bytes = 0; 427 442 char c; 428 429 while (socket->bytesAvailable()) { 443 qint64 haveRead = 0; 444 445 do { 446 haveRead = socket->read(&c, 1); 447 if (haveRead == -1) 448 return -1; // unexpected EOF 449 else if (haveRead == 0) 450 break; // read more later 451 452 bytes++; 453 430 454 // allow both CRLF & LF (only) line endings 431 if (socket->peek(&c, 1) == 1 && c == '\n') { 432 bytes += socket->read(&c, 1); // read the "n" 455 if (c == '\n') { 433 456 // remove the CR at the end 434 457 if (fragment.endsWith('\r')) { … … 443 466 break; 444 467 } else { 445 c = 0;446 int haveRead = socket->read(&c, 1);447 if (haveRead == -1)448 return -1;449 bytes += haveRead;450 468 fragment.append(c); 451 469 } … … 457 475 return -1; 458 476 } 459 460 } 477 } while (haveRead == 1); 461 478 462 479 return bytes; … … 501 518 qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) 502 519 { 520 if (fragment.isEmpty()) { 521 // according to http://dev.opera.com/articles/view/mama-http-headers/ the average size of the header 522 // block is 381 bytes. 523 // reserve bytes. This is better than always append() which reallocs the byte array. 524 fragment.reserve(512); 525 } 526 503 527 qint64 bytes = 0; 504 528 char c = 0; 505 529 bool allHeaders = false; 506 while (!allHeaders && socket->bytesAvailable()) { 507 if (socket->peek(&c, 1) == 1 && c == '\n') { 508 // check for possible header endings. As per HTTP rfc, 509 // the header endings will be marked by CRLFCRLF. But 510 // we will allow CRLFLF, LFLF & CRLFCRLF 511 if (fragment.endsWith("\n\r") || fragment.endsWith('\n')) 512 allHeaders = true; 513 } 514 bytes += socket->read(&c, 1); 515 fragment.append(c); 516 } 530 qint64 haveRead = 0; 531 do { 532 haveRead = socket->read(&c, 1); 533 if (haveRead == 0) { 534 // read more later 535 break; 536 } else if (haveRead == -1) { 537 // connection broke down 538 return -1; 539 } else { 540 fragment.append(c); 541 bytes++; 542 543 if (c == '\n') { 544 // check for possible header endings. As per HTTP rfc, 545 // the header endings will be marked by CRLFCRLF. But 546 // we will allow CRLFCRLF, CRLFLF, LFLF 547 if (fragment.endsWith("\r\n\r\n") 548 || fragment.endsWith("\r\n\n") 549 || fragment.endsWith("\n\n")) 550 allHeaders = true; 551 552 // there is another case: We have no headers. Then the fragment equals just the line ending 553 if ((fragment.length() == 2 && fragment.endsWith("\r\n")) 554 || (fragment.length() == 1 && fragment.endsWith("\n"))) 555 allHeaders = true; 556 } 557 } 558 } while (!allHeaders && haveRead > 0); 559 517 560 // we received all headers now parse them 518 561 if (allHeaders) { … … 776 819 { 777 820 Q_D(const QHttpNetworkReply); 778 if (d->connection) 779 return d->connection->d_func()->sslConfiguration(*this); 780 return QSslConfiguration(); 821 822 if (!d->connectionChannel) 823 return QSslConfiguration(); 824 825 QSslSocket *sslSocket = qobject_cast<QSslSocket*>(d->connectionChannel->socket); 826 if (!sslSocket) 827 return QSslConfiguration(); 828 829 return sslSocket->sslConfiguration(); 781 830 } 782 831 -
trunk/src/network/access/qhttpnetworkreply_p.h
r651 r769 87 87 88 88 class QHttpNetworkConnection; 89 class QHttpNetworkConnectionChannel; 89 90 class QHttpNetworkRequest; 90 91 class QHttpNetworkConnectionPrivate; … … 172 173 QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; 173 174 void clear(); 175 void clearHttpLayerInformation(); 174 176 175 177 qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); … … 219 221 qint64 currentChunkRead; 220 222 QPointer<QHttpNetworkConnection> connection; 223 QPointer<QHttpNetworkConnectionChannel> connectionChannel; 221 224 bool initInflate; 222 225 bool streamEnd; -
trunk/src/network/access/qnetworkaccessbackend.cpp
r651 r769 73 73 { 74 74 QMutexLocker locker(&factoryData()->mutex); 75 factoryData()-> prepend(this);75 factoryData()->append(this); 76 76 } 77 77 -
trunk/src/network/access/qnetworkaccesshttpbackend.cpp
r651 r769 681 681 682 682 while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) { 683 QByteArray data = httpReply->readAny(); 684 list.append(data); 683 list.append(httpReply->readAny()); 685 684 } 686 685 … … 754 753 if (!value.isEmpty()) { 755 754 if (qstricmp(it->first.constData(), "set-cookie") == 0) 756 value += "\n";755 value += '\n'; 757 756 else 758 757 value += ", "; … … 977 976 // write to disk when only the date changes). 978 977 // However, without the date we cannot calculate the age of the page 979 // anymore. Consider a proper fix of that problem for 4.6.1.978 // anymore. 980 979 //if (header == "date") 981 980 //continue; -
trunk/src/network/access/qnetworkaccesshttpbackend_p.h
r651 r769 95 95 QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const; 96 96 97 qint64 deviceReadData(char *buffer, qint64 maxlen);98 99 97 // we return true since HTTP needs to send PUT/POST data again after having authenticated 100 98 bool needsResetableUploadData() { return true; } -
trunk/src/network/access/qnetworkaccessmanager.cpp
r651 r769 108 108 it sends. It contains the proxy and cache configuration, as well as the 109 109 signals related to such issues, and reply signals that can be used to 110 monitor the progress of a network operation. 110 monitor the progress of a network operation. One QNetworkAccessManager 111 should be enough for the whole Qt application. 111 112 112 113 Once a QNetworkAccessManager object has been created, the application can … … 119 120 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 0 120 121 122 QNetworkAccessManager has an asynchronous API. 121 123 When the \tt replyFinished slot above is called, the parameter it 122 124 takes is the QNetworkReply object containing the downloaded data … … 128 130 deleteLater() function. 129 131 132 \note QNetworkAccessManager queues the requests it receives. The number 133 of requests executed in parallel is dependent on the protocol. 134 Currently, for the HTTP protocol on desktop platforms, 6 requests are 135 executed in parallel for one host/port combination. 136 130 137 A more involved example, assuming the manager is already existent, 131 138 can be: 132 139 \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 1 140 141 \section1 Symbian Platform Security Requirements 142 143 On Symbian, processes which use this class must have the 144 \c NetworkServices platform security capability. If the client 145 process lacks this capability, operations will result in a panic. 146 147 Platform security capabilities are added via the 148 \l{qmake-variable-reference.html#target-capability}{TARGET.CAPABILITY} 149 qmake variable. 133 150 134 151 \sa QNetworkRequest, QNetworkReply, QNetworkProxy … … 550 567 /*! 551 568 Posts a request to obtain the network headers for \a request 552 and returns a new QNetworkReply object which will contain such headers 569 and returns a new QNetworkReply object which will contain such headers. 553 570 554 571 The function is named after the HTTP request associated (HEAD). -
trunk/src/network/access/qnetworkcookie.h
r651 r769 115 115 116 116 // ### Qt5 remove this include 117 #include "qnetworkcookiejar.h"117 #include <QtNetwork/QNetworkCookieJar> 118 118 119 119 Q_DECLARE_METATYPE(QNetworkCookie) -
trunk/src/network/access/qnetworkcookiejar.h
r651 r769 47 47 48 48 // ### Qt5 remove this include 49 #include "qnetworkcookie.h"49 #include <QtNetwork/QNetworkCookie> 50 50 51 51 QT_BEGIN_HEADER -
trunk/src/network/access/qnetworkdiskcache.cpp
r651 r769 42 42 //#define QNETWORKDISKCACHE_DEBUG 43 43 44 #ifndef QT_NO_NETWORKDISKCACHE45 44 46 45 #include "qnetworkdiskcache.h" … … 60 59 #define CACHE_POSTFIX QLatin1String(".cache") 61 60 #define MAX_COMPRESSION_SIZE (1024 * 1024 * 3) 61 62 #ifndef QT_NO_NETWORKDISKCACHE 62 63 63 64 QT_BEGIN_NAMESPACE -
trunk/src/network/access/qnetworkdiskcache_p.h
r651 r769 60 60 #include <qtemporaryfile.h> 61 61 62 #ifndef QT_NO_NETWORKDISKCACHE 63 62 64 QT_BEGIN_NAMESPACE 63 65 … … 120 122 QT_END_NAMESPACE 121 123 124 #endif // QT_NO_NETWORKDISKCACHE 125 122 126 #endif // QNETWORKDISKCACHE_P_H -
trunk/src/network/access/qnetworkreplyimpl.cpp
r651 r769 404 404 } 405 405 406 void QNetworkReplyImplPrivate::initCacheSaveDevice() 407 { 408 Q_Q(QNetworkReplyImpl); 409 410 // save the meta data 411 QNetworkCacheMetaData metaData; 412 metaData.setUrl(url); 413 metaData = backend->fetchCacheMetaData(metaData); 414 415 // save the redirect request also in the cache 416 QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); 417 if (redirectionTarget.isValid()) { 418 QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); 419 attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); 420 metaData.setAttributes(attributes); 421 } 422 423 cacheSaveDevice = networkCache()->prepare(metaData); 424 425 if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { 426 if (cacheSaveDevice && !cacheSaveDevice->isOpen()) 427 qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " 428 "class %s probably needs to be fixed", 429 networkCache()->metaObject()->className()); 430 431 networkCache()->remove(url); 432 cacheSaveDevice = 0; 433 cacheEnabled = false; 434 } 435 } 436 406 437 // we received downstream data and send this to the cache 407 438 // and to our readBuffer (which in turn gets read by the user of QNetworkReply) … … 413 444 414 445 if (cacheEnabled && !cacheSaveDevice) { 415 // save the meta data 416 QNetworkCacheMetaData metaData; 417 metaData.setUrl(url); 418 metaData = backend->fetchCacheMetaData(metaData); 419 420 // save the redirect request also in the cache 421 QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); 422 if (redirectionTarget.isValid()) { 423 QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); 424 attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); 425 metaData.setAttributes(attributes); 426 } 427 428 cacheSaveDevice = networkCache()->prepare(metaData); 429 430 if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { 431 if (cacheSaveDevice && !cacheSaveDevice->isOpen()) 432 qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " 433 "class %s probably needs to be fixed", 434 networkCache()->metaObject()->className()); 435 436 networkCache()->remove(url); 437 cacheSaveDevice = 0; 438 cacheEnabled = false; 439 } 446 initCacheSaveDevice(); 440 447 } 441 448 442 449 qint64 bytesWritten = 0; 443 450 for (int i = 0; i < data.bufferCount(); i++) { 444 QByteArray item = data[i];451 QByteArray const &item = data[i]; 445 452 446 453 if (cacheSaveDevice) … … 454 461 bytesDownloaded += bytesWritten; 455 462 lastBytesDownloaded = bytesDownloaded; 463 464 appendDownstreamDataSignalEmissions(); 465 } 466 467 void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() 468 { 469 Q_Q(QNetworkReplyImpl); 456 470 457 471 QPointer<QNetworkReplyImpl> qq = q; … … 496 510 } 497 511 512 void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) 513 { 514 // TODO implement 515 516 // TODO call 517 518 qFatal("QNetworkReplyImplPrivate::appendDownstreamData not implemented"); 519 } 520 498 521 void QNetworkReplyImplPrivate::finished() 499 522 { … … 581 604 { 582 605 Q_D(QNetworkReplyImpl); 606 607 // This code removes the data from the cache if it was prematurely aborted. 608 // See QNetworkReplyImplPrivate::completeCacheSave(), we disable caching there after the cache 609 // save had been properly finished. So if it is still enabled it means we got deleted/aborted. 583 610 if (d->isCachingEnabled()) 584 611 d->networkCache()->remove(url()); 612 585 613 if (d->outgoingDataBuffer) 586 614 delete d->outgoingDataBuffer; -
trunk/src/network/access/qnetworkreplyimpl_p.h
r651 r769 146 146 void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal); 147 147 qint64 nextDownstreamBlockSize() const; 148 149 void initCacheSaveDevice(); 150 void appendDownstreamDataSignalEmissions(); 148 151 void appendDownstreamData(QByteDataBuffer &data); 149 152 void appendDownstreamData(QIODevice *data); 153 void appendDownstreamData(const QByteArray &data); 154 150 155 void finished(); 151 156 void error(QNetworkReply::NetworkError code, const QString &errorString); -
trunk/src/network/access/qnetworkrequest.cpp
r651 r769 139 139 determine if the requested redirection should be allowed, 140 140 according to its security policies. 141 The returned URL might be relative. Use QUrl::resolved() 142 to create an absolute URL out of it. 141 143 142 144 \value ConnectionEncryptedAttribute … … 650 652 QList<QNetworkCookie> result; 651 653 QList<QByteArray> cookieList = raw.split(';'); 652 foreach ( QByteArraycookie, cookieList) {654 foreach (const QByteArray &cookie, cookieList) { 653 655 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed()); 654 656 if (parsed.count() != 1)
Note:
See TracChangeset
for help on using the changeset viewer.