void Core::rejectFileRecvRequest(int friendId, int fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) { if (f.fileNum == fileNum && f.friendId == friendId) { file = &f; break; } } if (!file) { qWarning("Core::rejectFileRecvRequest: No such file in queue"); return; } file->status = ToxFile::STOPPED; emit fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); removeFileFromQueue(false, friendId, fileNum); }
void Core::cancelFileSend(int friendId, int fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileSendQueue) { if (f.fileNum == fileNum && f.friendId == friendId) { file = &f; break; } } if (!file) { qWarning("Core::cancelFileSend: No such file in queue"); return; } file->status = ToxFile::STOPPED; emit fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting removeFileFromQueue(true, friendId, fileNum); }
void Core::sendAllFileData(Core *core, ToxFile* file) { if (file->status == ToxFile::PAUSED) { file->sendTimer->start(TOX_FILE_INTERVAL); return; } else if (file->status == ToxFile::STOPPED) { qWarning("Core::sendAllFileData: File is stopped"); file->sendTimer->disconnect(); delete file->sendTimer; file->sendTimer = nullptr; return; } emit core->fileTransferInfo(file->friendId, file->fileNum, file->filesize, file->bytesSent, ToxFile::SENDING); qApp->processEvents(); long long chunkSize = tox_file_data_size(core->tox, file->friendId); if (chunkSize == -1) { qWarning("Core::fileHeartbeat: Error getting preffered chunk size, aborting file send"); file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); removeFileFromQueue(true, file->friendId, file->fileNum); return; } //qDebug() << "chunkSize: " << chunkSize; chunkSize = std::min(chunkSize, file->filesize); uint8_t* data = new uint8_t[chunkSize]; file->file->seek(file->bytesSent); int readSize = file->file->read((char*)data, chunkSize); if (readSize == -1) { qWarning() << QString("Core::sendAllFileData: Error reading from file: %1").arg(file->file->errorString()); delete[] data; file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); removeFileFromQueue(true, file->friendId, file->fileNum); return; } else if (readSize == 0) { qWarning() << QString("Core::sendAllFileData: Nothing to read from file: %1").arg(file->file->errorString()); delete[] data; file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); removeFileFromQueue(true, file->friendId, file->fileNum); return; } if (tox_file_send_data(core->tox, file->friendId, file->fileNum, data, readSize) == -1) { //qWarning("Core::fileHeartbeat: Error sending data chunk"); //core->process(); delete[] data; QThread::msleep(1); file->sendTimer->start(TOX_FILE_INTERVAL); return; } delete[] data; file->bytesSent += readSize; //qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file->bytesSent).arg(file->fileData.size()); if (file->bytesSent < file->filesize) { file->sendTimer->start(TOX_FILE_INTERVAL); return; } else { //qDebug("Core: File transfer finished"); file->sendTimer->disconnect(); delete file->sendTimer; file->sendTimer = nullptr; tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); //emit core->fileTransferFinished(*file); } }
void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, const uint8_t*, uint16_t, void *core) { ToxFile* file{nullptr}; if (receive_send == 1) { for (ToxFile& f : fileSendQueue) { if (f.fileNum == filenumber && f.friendId == friendnumber) { file = &f; break; } } } else { for (ToxFile& f : fileRecvQueue) { if (f.fileNum == filenumber && f.friendId == friendnumber) { file = &f; break; } } } if (!file) { qWarning("Core::onFileControlCallback: No such file in queue"); return; } if (receive_send == 1 && control_type == TOX_FILECONTROL_ACCEPT) { file->status = ToxFile::TRANSMITTING; emit static_cast<Core*>(core)->fileTransferAccepted(*file); qDebug() << "Core: File control callback, file accepted"; file->sendTimer = new QTimer(static_cast<Core*>(core)); connect(file->sendTimer, &QTimer::timeout, std::bind(sendAllFileData,static_cast<Core*>(core), file)); file->sendTimer->setSingleShot(true); file->sendTimer->start(TOX_FILE_INTERVAL); } else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); while (file->sendTimer) QThread::msleep(1); // Wait for sendAllFileData to return before deleting the ToxFile removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 to friend %2 is complete") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferFinished(*file); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 0 && control_type == TOX_FILECONTROL_KILL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::RECEIVING); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED) { qDebug() << QString("Core::onFileControlCallback: Reception of file %1 from %2 finished") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferFinished(*file); // confirm receive is complete tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else { qDebug() << QString("Core: File control callback, receive_send=%1, control_type=%2") .arg(receive_send).arg(control_type); } }
void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, const uint8_t* data, uint16_t length, void *core) { ToxFile* file{nullptr}; if (receive_send == 1) { for (ToxFile& f : fileSendQueue) { if (f.fileNum == filenumber && f.friendId == friendnumber) { file = &f; break; } } } else { for (ToxFile& f : fileRecvQueue) { if (f.fileNum == filenumber && f.friendId == friendnumber) { file = &f; break; } } } if (!file) { qWarning("Core::onFileControlCallback: No such file in queue"); return; } if (receive_send == 1 && control_type == TOX_FILECONTROL_ACCEPT) { file->status = ToxFile::TRANSMITTING; emit static_cast<Core*>(core)->fileTransferAccepted(*file); qDebug() << "Core: File control callback, file accepted"; file->sendTimer = new QTimer(static_cast<Core*>(core)); connect(file->sendTimer, &QTimer::timeout, std::bind(sendAllFileData,static_cast<Core*>(core), file)); file->sendTimer->setSingleShot(true); file->sendTimer->start(TOX_FILE_INTERVAL); } else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); // Wait for sendAllFileData to return before deleting the ToxFile, we MUST ensure this or we'll use after free if (file->sendTimer) { QThread::msleep(1); qApp->processEvents(); if (file->sendTimer) { delete file->sendTimer; file->sendTimer = nullptr; } } removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 to friend %2 is complete") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferFinished(*file); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 0 && control_type == TOX_FILECONTROL_KILL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::RECEIVING); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED) { qDebug() << QString("Core::onFileControlCallback: Reception of file %1 from %2 finished") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast<Core*>(core)->fileTransferFinished(*file); // confirm receive is complete tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } else if (receive_send == 0 && control_type == TOX_FILECONTROL_ACCEPT) { if (file->status == ToxFile::BROKEN) { emit static_cast<Core*>(core)->fileTransferBrokenUnbroken(*file, false); file->status = ToxFile::TRANSMITTING; } emit static_cast<Core*>(core)->fileTransferRemotePausedUnpaused(*file, false); } else if ((receive_send == 0 || receive_send == 1) && control_type == TOX_FILECONTROL_PAUSE) { emit static_cast<Core*>(core)->fileTransferRemotePausedUnpaused(*file, true); } else if (receive_send == 1 && control_type == TOX_FILECONTROL_RESUME_BROKEN) { if (length != sizeof(uint64_t)) return; qDebug() << "Core::onFileControlCallback: TOX_FILECONTROL_RESUME_BROKEN"; uint64_t resumePos = *reinterpret_cast<const uint64_t*>(data); if (resumePos >= file->filesize) { qWarning() << "Core::onFileControlCallback: invalid resume position"; tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); // don't sure about it return; } file->status = ToxFile::TRANSMITTING; emit static_cast<Core*>(core)->fileTransferBrokenUnbroken(*file, false); file->bytesSent = resumePos; tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); } else { qDebug() << QString("Core: File control callback, receive_send=%1, control_type=%2") .arg(receive_send).arg(control_type); } }