* @brief Sends a batch of data chunks, then yields to the event loop. */
| 470 | * @brief Sends a batch of data chunks, then yields to the event loop. |
| 471 | */ |
| 472 | void IO::Protocols::ZMODEM::sendNextDataChunk() |
| 473 | { |
| 474 | Q_ASSERT(m_blockSize >= 64 && m_blockSize <= 8192); |
| 475 | Q_ASSERT(m_file.isOpen()); |
| 476 | |
| 477 | if (m_state != State::SendingData) |
| 478 | return; |
| 479 | |
| 480 | for (int i = 0; i < kChunksPerYield && !m_file.atEnd(); ++i) { |
| 481 | QByteArray chunk = m_file.read(m_blockSize); |
| 482 | if (chunk.isEmpty()) { |
| 483 | qWarning() << "[ZMODEM] File read returned empty data at offset" << m_bytesSent; |
| 484 | break; |
| 485 | } |
| 486 | |
| 487 | if (chunk.size() > m_blockSize) [[unlikely]] { |
| 488 | Q_EMIT finished(false, tr("File read returned more data than requested")); |
| 489 | return; |
| 490 | } |
| 491 | |
| 492 | m_bytesSent += chunk.size(); |
| 493 | Q_EMIT progressChanged(m_bytesSent, m_fileSize); |
| 494 | |
| 495 | if (m_file.atEnd()) |
| 496 | Q_EMIT writeRequested(buildSubpacket(chunk, kZCRCE)); |
| 497 | else |
| 498 | Q_EMIT writeRequested(buildSubpacket(chunk, kZCRCG)); |
| 499 | } |
| 500 | |
| 501 | if (!m_file.atEnd() && m_state == State::SendingData) |
| 502 | QTimer::singleShot(0, this, &ZMODEM::sendNextDataChunk); |
| 503 | else if (m_state == State::SendingData) |
| 504 | sendZEOF(); |
| 505 | } |
| 506 | |
| 507 | /** |
| 508 | * @brief Sends the ZEOF header. |