1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Move file transfer in the core thread

Toxcore is not thread safe
This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-08-28 21:56:55 +02:00
parent a75d1c5c6e
commit 3fc37d2d4c
2 changed files with 78 additions and 63 deletions

137
core.cpp
View File

@ -21,6 +21,7 @@
#include "widget/widget.h" #include "widget/widget.h"
#include <ctime> #include <ctime>
#include <functional>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
@ -45,8 +46,6 @@ Core::Core(Camera* cam, QThread *coreThread) :
toxTimer->setSingleShot(true); toxTimer->setSingleShot(true);
//saveTimer = new QTimer(this); //saveTimer = new QTimer(this);
//saveTimer->start(TOX_SAVE_INTERVAL); //saveTimer->start(TOX_SAVE_INTERVAL);
//fileTimer = new QTimer(this);
//fileTimer->start(TOX_FILE_INTERVAL);
bootstrapTimer = new QTimer(this); bootstrapTimer = new QTimer(this);
bootstrapTimer->start(TOX_BOOTSTRAP_INTERVAL); bootstrapTimer->start(TOX_BOOTSTRAP_INTERVAL);
connect(toxTimer, &QTimer::timeout, this, &Core::process); connect(toxTimer, &QTimer::timeout, this, &Core::process);
@ -304,7 +303,10 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
file->status = ToxFile::TRANSMITTING; file->status = ToxFile::TRANSMITTING;
emit static_cast<Core*>(core)->fileTransferAccepted(*file); emit static_cast<Core*>(core)->fileTransferAccepted(*file);
qDebug() << "Core: File control callback, file accepted"; qDebug() << "Core: File control callback, file accepted";
file->sendFuture = QtConcurrent::run(sendAllFileData, static_cast<Core*>(core), file); 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) else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL)
{ {
@ -312,7 +314,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
.arg(file->fileNum).arg(file->friendId); .arg(file->fileNum).arg(file->friendId);
file->status = ToxFile::STOPPED; file->status = ToxFile::STOPPED;
emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING);
file->sendFuture.waitForFinished(); // Wait for sendAllFileData to return before deleting the ToxFile while (file->sendTimer) QThread::msleep(1); // Wait for sendAllFileData to return before deleting the ToxFile
removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum);
} }
else if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED) else if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED)
@ -532,7 +534,7 @@ void Core::cancelFileSend(int friendId, int fileNum)
file->status = ToxFile::STOPPED; file->status = ToxFile::STOPPED;
emit fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); emit fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING);
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
file->sendFuture.waitForFinished(); // Wait until sendAllFileData returns before deleting while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting
removeFileFromQueue(true, friendId, fileNum); removeFileFromQueue(true, friendId, fileNum);
} }
@ -961,64 +963,77 @@ void Core::removeFileFromQueue(bool sendQueue, int friendId, int fileId)
void Core::sendAllFileData(Core *core, ToxFile* file) void Core::sendAllFileData(Core *core, ToxFile* file)
{ {
while (file->bytesSent < file->filesize) if (file->status == ToxFile::PAUSED)
{ {
if (file->status == ToxFile::PAUSED) file->sendTimer->start(TOX_FILE_INTERVAL);
{ return;
QThread::sleep(1); }
continue; else if (file->status == ToxFile::STOPPED)
} {
else if (file->status == ToxFile::STOPPED) qWarning("Core::sendAllFileData: File is stopped");
{ file->sendTimer->disconnect();
qWarning("Core::sendAllFileData: File is stopped"); delete file->sendTimer;
return; file->sendTimer = nullptr;
} return;
emit core->fileTransferInfo(file->friendId, file->fileNum, file->filesize, file->bytesSent, ToxFile::SENDING); }
qApp->processEvents(); emit core->fileTransferInfo(file->friendId, file->fileNum, file->filesize, file->bytesSent, ToxFile::SENDING);
long long chunkSize = tox_file_data_size(core->tox, file->friendId); qApp->processEvents();
if (chunkSize == -1) 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; qWarning("Core::fileHeartbeat: Error getting preffered chunk size, aborting file send");
emit core->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING); file->status = ToxFile::STOPPED;
tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); emit core->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING);
removeFileFromQueue(true, file->friendId, file->fileNum); tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
return; removeFileFromQueue(true, file->friendId, file->fileNum);
} return;
//qDebug() << "chunkSize: " << chunkSize; }
chunkSize = std::min(chunkSize, file->filesize); //qDebug() << "chunkSize: " << chunkSize;
uint8_t* data = new uint8_t[chunkSize]; chunkSize = std::min(chunkSize, file->filesize);
file->file->seek(file->bytesSent); uint8_t* data = new uint8_t[chunkSize];
int readSize = file->file->read((char*)data, chunkSize); file->file->seek(file->bytesSent);
if (readSize == -1) 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; qWarning() << QString("Core::sendAllFileData: Error reading from file: %1").arg(file->file->errorString());
QThread::msleep(5); delete[] data;
continue; file->sendTimer->start(TOX_FILE_INTERVAL);
} return;
else if (readSize == 0) }
{ else if (readSize == 0)
qWarning() << QString("Core::sendAllFileData: Nothing to read from file: %1").arg(file->file->errorString()); {
delete[] data; qWarning() << QString("Core::sendAllFileData: Nothing to read from file: %1").arg(file->file->errorString());
QThread::msleep(5); delete[] data;
continue; file->sendTimer->start(TOX_FILE_INTERVAL);
} return;
if (tox_file_send_data(core->tox, file->friendId, file->fileNum, data, readSize) == -1) }
{ if (tox_file_send_data(core->tox, file->friendId, file->fileNum, data, readSize) == -1)
//qWarning("Core::fileHeartbeat: Error sending data chunk"); {
//core->process(); //qWarning("Core::fileHeartbeat: Error sending data chunk");
delete[] data; //core->process();
QThread::msleep(5); delete[] data;
continue; QThread::msleep(1);
} file->sendTimer->start(TOX_FILE_INTERVAL);
delete[] data; return;
file->bytesSent += readSize; }
//qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file->bytesSent).arg(file->fileData.size()); 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);
} }
qDebug("Core::fileHeartbeat: Transfer finished");
tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0);
emit core->fileTransferFinished(*file);
} }
void Core::groupInviteFriend(int friendId, int groupId) void Core::groupInviteFriend(int friendId, int groupId)

4
core.h
View File

@ -39,7 +39,7 @@
#define TOXAV_MAX_CALLS 16 #define TOXAV_MAX_CALLS 16
#define GROUPCHAT_MAX_SIZE 32 #define GROUPCHAT_MAX_SIZE 32
#define TOX_SAVE_INTERVAL 30*1000 #define TOX_SAVE_INTERVAL 30*1000
#define TOX_FILE_INTERVAL 20 #define TOX_FILE_INTERVAL 1
#define TOX_BOOTSTRAP_INTERVAL 10*1000 #define TOX_BOOTSTRAP_INTERVAL 10*1000
#define TOXAV_RINGING_TIME 15 #define TOXAV_RINGING_TIME 15
@ -91,7 +91,7 @@ struct ToxFile
long long filesize; long long filesize;
FileStatus status; FileStatus status;
FileDirection direction; FileDirection direction;
QFuture<void> sendFuture; QTimer* sendTimer;
}; };
struct ToxCall struct ToxCall