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(errorString()); 120 121 if (.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->ileSize = fi.size(); 130 135 setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); 131 setHeader(QNetworkRequest::ContentLengthHeader, d-> realFileSize);136 setHeader(QNetworkRequest::ContentLengthHeader, d->ileSize); 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->ileSize)); 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->ileSize; 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 60 61 61 62 QT_BEGIN_NAMESPACE … … 86 87 public: 87 88 QFileNetworkReplyPrivate(); 89 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 2314 2315 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 77 78 77 79 78 80 … … 405 407 reply->setRequest(request); 406 408 reply->d_func()->connection = q; 409 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 424 425 426 427 428 429 419 430 _q_startNextRequest(); 431 432 420 433 return reply; 421 434 } … … 423 436 void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) 424 437 { 438 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 ); 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 718 719 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 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 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 61 83 void QHttpNetworkConnectionChannel::init() 62 84 { … … 125 147 bool QHttpNetworkConnectionChannel::sendRequest() 126 148 { 149 150 151 152 153 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 s; 170 ; 171 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 208 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(); 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 314 315 316 317 318 319 320 321 322 323 324 325 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 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 = replytate; 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 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 ; 350 396 } 351 397 } … … 417 463 } 418 464 } 465 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 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 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 640 641 642 643 644 645 646 647 648 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 || || 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 698 699 700 701 702 703 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 794 795 796 797 798 799 800 801 802 803 804 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 884 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<Q> 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 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 147 154 148 void pipelineInto(HttpMessagePair &pair); 155 149 void requeueCurrentlyPipelinedRequests(); 156 150 void detectPipeliningSupport(); 157 151 152 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 (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 183 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::clear() 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 242 243 244 245 246 247 248 239 249 autoDecompress = false; 240 fields.clear();250 (); 241 251 } 242 252 … … 424 434 qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) 425 435 { 436 437 438 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 521 522 523 524 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 89 90 class QHttpNetworkRequest; 90 91 class QHttpNetworkConnectionPrivate; … … 172 173 QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; 173 174 void clear(); 175 174 176 175 177 qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); … … 219 221 qint64 currentChunkRead; 220 222 QPointer<QHttpNetworkConnection> connection; 223 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()->pend(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 += ; 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 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 133 134 135 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 142 143 144 145 146 147 148 149 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 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 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 62 63 63 64 QT_BEGIN_NAMESPACE -
trunk/src/network/access/qnetworkdiskcache_p.h
r651 r769 60 60 #include <qtemporaryfile.h> 61 61 62 63 62 64 QT_BEGIN_NAMESPACE 63 65 … … 120 122 QT_END_NAMESPACE 121 123 124 125 122 126 #endif // QNETWORKDISKCACHE_P_H -
trunk/src/network/access/qnetworkreplyimpl.cpp
r651 r769 404 404 } 405 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 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 item = data[i]; 445 452 446 453 if (cacheSaveDevice) … … 454 461 bytesDownloaded += bytesWritten; 455 462 lastBytesDownloaded = bytesDownloaded; 463 464 465 466 467 468 469 456 470 457 471 QPointer<QNetworkReplyImpl> qq = q; … … 496 510 } 497 511 512 513 514 515 516 517 518 519 520 498 521 void QNetworkReplyImplPrivate::finished() 499 522 { … … 581 604 { 582 605 Q_D(QNetworkReplyImpl); 606 607 608 609 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 150 148 151 void appendDownstreamData(QByteDataBuffer &data); 149 152 void appendDownstreamData(QIODevice *data); 153 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 142 141 143 142 144 \value ConnectionEncryptedAttribute … … 650 652 QList<QNetworkCookie> result; 651 653 QList<QByteArray> cookieList = raw.split(';'); 652 foreach ( QByteArraycookie, cookieList) {654 foreach (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.