void QNetworkReplyImplPrivate::_q_copyReadyRead() { Q_Q(QNetworkReplyImpl); if (state != Working) return; if (!copyDevice || !q->isOpen()) return; // FIXME Optimize to use download buffer if it is a QBuffer. // Needs to be done where sendCacheContents() (?) of HTTP is emitting // metaDataChanged ? forever { qint64 bytesToRead = nextDownstreamBlockSize(); if (bytesToRead == 0) // we'll be called again, eventually break; bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable()); QByteArray byteData; byteData.resize(bytesToRead); qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size()); if (bytesActuallyRead == -1) { byteData.clear(); backendNotify(NotifyCopyFinished); break; } byteData.resize(bytesActuallyRead); readBuffer.append(byteData); if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); bytesDownloaded += bytesActuallyRead; break; } bytesDownloaded += bytesActuallyRead; } if (bytesDownloaded == lastBytesDownloaded) { // we didn't read anything return; } lastBytesDownloaded = bytesDownloaded; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; pauseNotificationHandling(); // emit readyRead before downloadProgress incase this will cause events to be // processed and we get into a recursive call (as in QProgressDialog). emit q->readyRead(); if (downloadProgressSignalChoke.elapsed() >= progressSignalInterval) { downloadProgressSignalChoke.restart(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); } resumeNotificationHandling(); }
bool QNetworkAccessFileBackend::readMoreFromFile() { qint64 wantToRead; while ((wantToRead = nextDownstreamBlockSize()) > 0) { // ### FIXME!! // Obtain a pointer from the ringbuffer! // Avoid extra copy QByteArray data; data.reserve(wantToRead); qint64 actuallyRead = file.read(data.data(), wantToRead); if (actuallyRead <= 0) { // EOF or error if (file.error() != QFile::NoError) { QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Read error reading from %1: %2") .arg(url().toString(), file.errorString()); error(QNetworkReply::ProtocolFailure, msg); finished(); return false; } finished(); return true; } data.resize(actuallyRead); totalBytes += actuallyRead; QByteDataBuffer list; list.append(data); data.clear(); // important because of implicit sharing! writeDownstreamData(list); } return true; }
void QNetworkAccessHttpBackend::readFromHttp() { if (!httpReply) return; // We read possibly more than nextDownstreamBlockSize(), but // this is not a critical thing since it is already in the // memory anyway QByteDataBuffer list; while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0 && nextDownstreamBlockSize() > list.byteAmount()) { list.append(httpReply->readAny()); } if (!list.isEmpty()) writeDownstreamData(list); }
void QNetworkAccessHttpBackend::readFromHttp() { // We implement the download rate control // Don't read from QHttpNetworkAccess more than QNetworkAccessBackend wants // One of the two functions above will be called when we can read again qint64 bytesToRead = qBound<qint64>(0, httpReply->bytesAvailable(), nextDownstreamBlockSize()); if (!bytesToRead) return; QByteArray data = httpReply->read(bytesToRead); writeDownstreamData(data); }
void QNetworkReplyImplPrivate::_q_copyReadyRead() { Q_Q(QNetworkReplyImpl); if (state != Working) return; if (!copyDevice || !q->isOpen()) return; forever { qint64 bytesToRead = nextDownstreamBlockSize(); if (bytesToRead == 0) // we'll be called again, eventually break; bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable()); QByteArray byteData; byteData.resize(bytesToRead); qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size()); if (bytesActuallyRead == -1) { byteData.clear(); backendNotify(NotifyCopyFinished); break; } byteData.resize(bytesActuallyRead); readBuffer.append(byteData); if (!copyDevice->isSequential() && copyDevice->atEnd()) { backendNotify(NotifyCopyFinished); bytesDownloaded += bytesActuallyRead; break; } bytesDownloaded += bytesActuallyRead; } if (bytesDownloaded == lastBytesDownloaded) { // we didn't read anything return; } lastBytesDownloaded = bytesDownloaded; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); emit q->readyRead(); resumeNotificationHandling(); }
void QNetworkAccessDebugPipeBackend::socketReadyRead() { if (bareProtocol) { qint64 bytesToRead = socket.bytesAvailable(); if (bytesToRead) { QByteArray buffer; buffer.resize(bytesToRead); qint64 bytesRead = socket.read(buffer.data(), bytesToRead); if (bytesRead < bytesToRead) buffer.truncate(bytesRead); writeDownstreamData(buffer); readyReadEmitted = true; } return; } while (canReceive() && (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) { DataPacket packet; if (receive(packet)) { if (!packet.headers.isEmpty()) { QList<QPair<QByteArray, QByteArray> >::ConstIterator it = packet.headers.constBegin(), end = packet.headers.constEnd(); for ( ; it != end; ++it) setRawHeader(it->first, it->second); metaDataChanged(); } if (!packet.data.isEmpty()) { writeDownstreamData(packet.data); readyReadEmitted = true; } if (packet.headers.isEmpty() && packet.data.isEmpty()) { // it's an eof socket.close(); readyReadEmitted = true; } } else { // got an error QString msg = QObject::tr("Read error reading from %1: %2") .arg(url().toString(), socket.errorString()); error(QNetworkReply::ProtocolFailure, msg); finished(); return; } } }
void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() { Q_Q(QNetworkReplyImpl); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; pauseNotificationHandling(); // important: At the point of this readyRead(), the data parameter list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); // emit readyRead before downloadProgress incase this will cause events to be // processed and we get into a recursive call (as in QProgressDialog). emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); resumeNotificationHandling(); // do we still have room in the buffer? if (nextDownstreamBlockSize() > 0) backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); }
void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() { Q_Q(QNetworkReplyImpl); QPointer<QNetworkReplyImpl> qq = q; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); // important: At the point of this readyRead(), the data parameter list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); // hopefully we haven't been deleted here if (!qq.isNull()) { resumeNotificationHandling(); // do we still have room in the buffer? if (nextDownstreamBlockSize() > 0) backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); } }
// we received downstream data and send this to the cache // and to our readBuffer (which in turn gets read by the user of QNetworkReply) void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) { Q_Q(QNetworkReplyImpl); if (!q->isOpen()) return; if (cacheEnabled && !cacheSaveDevice) { // save the meta data QNetworkCacheMetaData metaData; metaData.setUrl(url); metaData = backend->fetchCacheMetaData(metaData); // save the redirect request also in the cache QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); if (redirectionTarget.isValid()) { QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); metaData.setAttributes(attributes); } cacheSaveDevice = networkCache()->prepare(metaData); if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { if (cacheSaveDevice && !cacheSaveDevice->isOpen()) qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " "class %s probably needs to be fixed", networkCache()->metaObject()->className()); networkCache()->remove(url); cacheSaveDevice = 0; cacheEnabled = false; } } qint64 bytesWritten = 0; for (int i = 0; i < data.bufferCount(); i++) { QByteArray item = data[i]; if (cacheSaveDevice) cacheSaveDevice->write(item.constData(), item.size()); readBuffer.append(item); bytesWritten += item.size(); } data.clear(); bytesDownloaded += bytesWritten; lastBytesDownloaded = bytesDownloaded; QPointer<QNetworkReplyImpl> qq = q; QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; pauseNotificationHandling(); emit q->downloadProgress(bytesDownloaded, totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong()); // important: At the point of this readyRead(), the data parameter list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); // hopefully we haven't been deleted here if (!qq.isNull()) { resumeNotificationHandling(); // do we still have room in the buffer? if (nextDownstreamBlockSize() > 0) backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); } }