From 9dedd22bb26e8581310a03275839a64c45d9809f Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 15:31:30 +0200 Subject: [PATCH] Port file transfers to the new API Parallel, extremely large, and other edge case transfers have not been tested, but the common path should work well. --- src/chatlog/content/filetransferwidget.cpp | 34 ++- src/chatlog/content/filetransferwidget.h | 4 +- src/core/core.cpp | 207 +-------------- src/core/core.h | 6 +- src/core/corefile.cpp | 286 ++++++++++++++++++++- src/core/corefile.h | 33 ++- src/core/corestructs.cpp | 5 +- src/core/corestructs.h | 5 +- src/ipc.cpp | 1 + 9 files changed, 365 insertions(+), 216 deletions(-) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 466138dbf..2139f445c 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -77,6 +77,7 @@ FileTransferWidget::FileTransferWidget(QWidget *parent, ToxFile file) connect(Core::getInstance(), &Core::fileTransferCancelled, this, &FileTransferWidget::onFileTransferCancelled); connect(Core::getInstance(), &Core::fileTransferPaused, this, &FileTransferWidget::onFileTransferPaused); connect(Core::getInstance(), &Core::fileTransferFinished, this, &FileTransferWidget::onFileTransferFinished); + connect(Core::getInstance(), &Core::fileTransferRemotePausedUnpaused, this, &FileTransferWidget::fileTransferRemotePausedUnpaused); setupButtons(); @@ -222,7 +223,10 @@ void FileTransferWidget::onFileTransferInfo(ToxFile file) // ETA, speed qreal deltaSecs = dt / 1000.0; - qint64 deltaBytes = qMax(file.bytesSent - lastBytesSent, qint64(0)); + // (can't use ::abs or ::max on unsigned types substraction, they'd just overflow) + quint64 deltaBytes = file.bytesSent > lastBytesSent + ? file.bytesSent - lastBytesSent + : lastBytesSent - file.bytesSent; qreal bytesPerSec = static_cast(static_cast(deltaBytes) / deltaSecs); // calculate mean @@ -306,6 +310,26 @@ void FileTransferWidget::onFileTransferPaused(ToxFile file) setupButtons(); } +void FileTransferWidget::onFileTransferResumed(ToxFile file) +{ + if(fileInfo != file) + return; + + fileInfo = file; + + ui->etaLabel->setText(""); + ui->progressLabel->setText(tr("Resuming...", "file transfer widget")); + + // reset mean + meanIndex = 0; + for(size_t i=0; i Core::fileSendQueue; -QList Core::fileRecvQueue; QHash Core::groupCalls; QThread* Core::coreThread{nullptr}; @@ -69,7 +67,6 @@ Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) : toxTimer = new QTimer(this); toxTimer->setSingleShot(true); connect(toxTimer, &QTimer::timeout, this, &Core::process); - //connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat); connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::process); for (int i=0; i(core)->checkLastOnline(friendId); + /** TODO: Review file sending breaking/resuming for (ToxFile& f : fileSendQueue) { if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) @@ -502,9 +500,11 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->fileTransferBrokenUnbroken(f, true); } } + */ } else { + /** for (ToxFile& f : fileRecvQueue) { if (f.friendId == friendId && f.status == ToxFile::BROKEN) @@ -514,6 +514,7 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->fileTransferBrokenUnbroken(f, false); } } + */ } } @@ -680,186 +681,37 @@ void Core::changeGroupTitle(int groupId, const QString& title) void Core::sendFile(uint32_t friendId, QString Filename, QString FilePath, long long filesize) { - QMutexLocker mlocker(&fileSendMutex); - - QByteArray fileName = Filename.toUtf8(); - uint32_t fileNum = tox_file_send(tox, friendId, TOX_FILE_KIND_DATA, filesize, nullptr, - (uint8_t*)fileName.data(), fileName.size(), nullptr); - if (fileNum == UINT32_MAX) - { - qWarning() << "Core::sendFile: Can't create the Tox file sender"; - emit fileSendFailed(friendId, Filename); - return; - } - qDebug() << QString("Core::sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); - - ToxFile file{fileNum, friendId, fileName, FilePath, ToxFile::SENDING}; - file.filesize = filesize; - if (!file.open(false)) - { - qWarning() << QString("Core::sendFile: Can't open file, error: %1").arg(file.file->errorString()); - } - fileSendQueue.append(file); - - emit fileSendStarted(fileSendQueue.last()); + CoreFile::sendFile(this, friendId, Filename, FilePath, filesize); } void Core::pauseResumeFileSend(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileSendQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::pauseResumeFileSend: No such file in queue"); - return; - } - if (file->status == ToxFile::TRANSMITTING) - { - file->status = ToxFile::PAUSED; - emit fileTransferPaused(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); - } - else if (file->status == ToxFile::PAUSED) - { - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - } - else - qWarning() << "Core::pauseResumeFileSend: File is stopped"; + CoreFile::pauseResumeFileSend(this, friendId, fileNum); } void Core::pauseResumeFileRecv(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::cancelFileRecv: No such file in queue"); - return; - } - if (file->status == ToxFile::TRANSMITTING) - { - file->status = ToxFile::PAUSED; - emit fileTransferPaused(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); - } - else if (file->status == ToxFile::PAUSED) - { - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - } - else - qWarning() << "Core::pauseResumeFileRecv: File is stopped or broken"; + CoreFile::pauseResumeFileRecv(this, friendId, fileNum); } void Core::cancelFileSend(uint32_t friendId, uint32_t 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); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting - removeFileFromQueue(true, friendId, fileNum); + CoreFile::cancelFileSend(this, friendId, fileNum); } void Core::cancelFileRecv(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::cancelFileRecv: No such file in queue"); - return; - } - file->status = ToxFile::STOPPED; - emit fileTransferCancelled(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(true, friendId, fileNum); + CoreFile::cancelFileRecv(this, friendId, fileNum); } void Core::rejectFileRecvRequest(uint32_t friendId, uint32_t 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); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(false, friendId, fileNum); + CoreFile::rejectFileRecvRequest(this, friendId, fileNum); } void Core::acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::acceptFileRecvRequest: No such file in queue"); - return; - } - file->setFilePath(path); - if (!file->open(true)) - { - qWarning() << "Core::acceptFileRecvRequest: Unable to open file"; - return; - } - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + CoreFile::acceptFileRecvRequest(this, friendId, fileNum, path); } void Core::removeFriend(uint32_t friendId, bool fake) @@ -1269,43 +1121,6 @@ void Core::quitGroupChat(int groupId) const tox_del_groupchat(tox, groupId); } -void Core::removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId) -{ - bool found = false; - if (sendQueue) - { - for (int i=0; iclose(); - delete fileSendQueue[i].file; - fileSendQueue.removeAt(i); - continue; - } - i++; - } - } - else - { - for (int i=0; iclose(); - delete fileRecvQueue[i].file; - fileRecvQueue.removeAt(i); - continue; - } - i++; - } - } - if (!found) - qWarning() << "Core::removeFileFromQueue: No such file in queue"; -} - void Core::groupInviteFriend(uint32_t friendId, int groupId) { tox_invite_friend(tox, friendId, groupId); diff --git a/src/core/core.h b/src/core/core.h index e01b7d5ae..32105b29e 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -278,8 +278,6 @@ private: void make_tox(QByteArray savedata); void loadFriends(); - static void removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId); - void checkLastOnline(uint32_t friendId); void deadifyTox(); @@ -292,13 +290,12 @@ private: QString loadPath; // meaningless after start() is called QList dhtServerList; int dhtServerId; - static QList fileSendQueue, fileRecvQueue; static ToxCall calls[TOXAV_MAX_CALLS]; #ifdef QTOX_FILTER_AUDIO static AudioFilterer * filterer[TOXAV_MAX_CALLS]; #endif static QHash groupCalls; // Maps group IDs to ToxGroupCalls - QMutex fileSendMutex, messageSendMutex; + QMutex messageSendMutex; bool ready; TOX_PASS_KEY* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw" @@ -319,6 +316,7 @@ private: static QThread *coreThread; friend class Audio; ///< Audio can access our calls directly to reduce latency + friend class CoreFile; ///< CoreFile can access tox* and emit our signals }; #endif // CORE_HPP diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index d636d25c7..893106bd1 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -1,26 +1,298 @@ +#include "core.h" #include "corefile.h" +#include "corestructs.h" +#include "src/misc/cstring.h" #include +#include +#include +#include + +QMutex CoreFile::fileSendMutex; +QHash CoreFile::fileMap; +using namespace std; + +void CoreFile::sendFile(Core* core, uint32_t friendId, QString Filename, QString FilePath, long long filesize) +{ + QMutexLocker mlocker(&fileSendMutex); + + QByteArray fileName = Filename.toUtf8(); + uint32_t fileNum = tox_file_send(core->tox, friendId, TOX_FILE_KIND_DATA, filesize, nullptr, + (uint8_t*)fileName.data(), fileName.size(), nullptr); + if (fileNum == UINT32_MAX) + { + qWarning() << "CoreFile::sendFile: Can't create the Tox file sender"; + emit core->fileSendFailed(friendId, Filename); + return; + } + qDebug() << QString("CoreFile::sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); + + ToxFile file{fileNum, friendId, fileName, FilePath, ToxFile::SENDING}; + file.filesize = filesize; + if (!file.open(false)) + { + qWarning() << QString("CoreFile::sendFile: Can't open file, error: %1").arg(file.file->errorString()); + } + addFile(friendId, fileNum, file); + + emit core->fileSendStarted(file); +} + +void CoreFile::pauseResumeFileSend(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::pauseResumeFileSend: No such file in queue"); + return; + } + if (file->status == ToxFile::TRANSMITTING) + { + file->status = ToxFile::PAUSED; + emit core->fileTransferPaused(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); + } + else if (file->status == ToxFile::PAUSED) + { + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + } + else + qWarning() << "CoreFile::pauseResumeFileSend: File is stopped"; +} + +void CoreFile::pauseResumeFileRecv(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileRecv: No such file in queue"); + return; + } + if (file->status == ToxFile::TRANSMITTING) + { + file->status = ToxFile::PAUSED; + emit core->fileTransferPaused(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); + } + else if (file->status == ToxFile::PAUSED) + { + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + } + else + qWarning() << "CoreFile::pauseResumeFileRecv: File is stopped or broken"; +} + +void CoreFile::cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileSend: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting + removeFile(friendId, fileId); +} + +void CoreFile::cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileRecv: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); +} + +void CoreFile::rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::rejectFileRecvRequest: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); +} + +void CoreFile::acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::acceptFileRecvRequest: No such file in queue"); + return; + } + file->setFilePath(path); + if (!file->open(true)) + { + qWarning() << "CoreFile::acceptFileRecvRequest: Unable to open file"; + return; + } + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); +} + +ToxFile* CoreFile::findFile(uint32_t friendId, uint32_t fileId) +{ + uint64_t key = ((uint64_t)friendId<<32) + (uint64_t)fileId; + if (!fileMap.contains(key)) + { + qWarning() << "CoreFile::addFile: File transfer with ID "<(core)->fileReceiveRequested(file); } -void CoreFile::onFileControlCallback(Tox* tox, uint32_t friendnumber, uint32_t filenumber, +void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId, TOX_FILE_CONTROL control, void *core) { - qDebug() << "File control "<(core)->fileTransferCancelled(*file); + removeFile(friendId, fileId); + } + else if (control == TOX_FILE_CONTROL_PAUSE) + { + qDebug() << "CoreFile::onFileControlCallback: Received pause for file "<status = ToxFile::PAUSED; + emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, true); + } + else if (control == TOX_FILE_CONTROL_RESUME) + { + qDebug() << "CoreFile::onFileControlCallback: Received pause for file "<status = ToxFile::TRANSMITTING; + emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, false); + } + else + { + qWarning() << "Unhandled file control "<(core)->fileTransferFinished(*file); + removeFile(friendId, fileId); + return; + } + + unique_ptr data(new uint8_t[length]); + + file->file->seek(pos); + int64_t nread = file->file->read((char*)data.get(), length); + if (nread <= 0) + { + qWarning("CoreFile::onFileDataCallback: Failed to read from file"); + emit static_cast(core)->fileTransferCancelled(*file); + tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr); + removeFile(friendId, fileId); + return; + } + file->bytesSent += length; + + if (!tox_file_send_chunk(tox, friendId, fileId, pos, data.get(), nread, nullptr)) + { + qWarning("CoreFile::onFileDataCallback: Failed to send data chunk"); + return; + } + emit static_cast(core)->fileTransferInfo(*file); } void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core) { - qDebug() << QString("Core: Received file chunk for request %1:%2").arg(friendId).arg(fileId); + //qDebug() << QString("CoreFile: Received file chunk for request %1:%2").arg(friendId).arg(fileId); + + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::onFileRecvChunkCallback: No such file in queue"); + tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); + return; + } + + if (file->bytesSent != position) + { + /// TODO: Allow ooo receiving for non-stream transfers, with very careful checking + qWarning("CoreFile::onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer"); + emit static_cast(core)->fileTransferCancelled(*file); + tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); + return; + } + file->bytesSent += length; + file->file->write((char*)data,length); + //qDebug() << QString("CoreFile::onFileRecvChunkCallback: received %1/%2 bytes").arg(file->bytesSent).arg(file->filesize); + + if (file->bytesSent == file->filesize) + emit static_cast(core)->fileTransferFinished(*file); + else + emit static_cast(core)->fileTransferInfo(*file); } diff --git a/src/core/corefile.h b/src/core/corefile.h index 1be64422d..cf8816524 100644 --- a/src/core/corefile.h +++ b/src/core/corefile.h @@ -3,26 +3,53 @@ #include #include +#include #include +#include "corestructs.h" + +#include +#include +#include + struct Tox; +class Core; /// Implements Core's file transfer callbacks /// Avoids polluting core.h with private internal callbacks class CoreFile { + friend class Core; + private: CoreFile()=delete; -public: +private: + static void sendFile(Core *core, uint32_t friendId, QString Filename, QString FilePath, long long filesize); + static void pauseResumeFileSend(Core* core, uint32_t friendId, uint32_t fileId); + static void pauseResumeFileRecv(Core* core, uint32_t friendId, uint32_t fileId); + static void cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId); + static void cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId); + static void rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId); + static void acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path); + static ToxFile *findFile(uint32_t friendId, uint32_t fileId); + static void addFile(uint32_t friendId, uint32_t fileId, const ToxFile& file); + static void removeFile(uint32_t friendId, uint32_t fileId); + +private: static void onFileReceiveCallback(Tox*, uint32_t friendnumber, uint32_t fileId, uint32_t kind, uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *core); - static void onFileControlCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + static void onFileControlCallback(Tox *tox, uint32_t friendId, uint32_t fileId, TOX_FILE_CONTROL control, void *core); - static void onFileDataCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + static void onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t pos, size_t length, void *core); static void onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core); + +private: + static QMutex fileSendMutex; + static QHash fileMap; + /// TODO: Replace the two queues by a hash map uint64_t -> unique_ptr }; #endif // COREFILE_H diff --git a/src/core/corestructs.cpp b/src/core/corestructs.cpp index 6dbc73271..20362b9bb 100644 --- a/src/core/corestructs.cpp +++ b/src/core/corestructs.cpp @@ -7,8 +7,9 @@ #define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE ToxFile::ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString FilePath, FileDirection Direction) - : fileNum(FileNum), friendId(FriendId), fileName{FileName}, filePath{FilePath}, file{new QFile(filePath)}, - bytesSent{0}, filesize{0}, status{STOPPED}, direction{Direction}, sendTimer{nullptr} + : fileKind{TOX_FILE_KIND_DATA}, fileNum(FileNum), friendId(FriendId), fileName{FileName}, + filePath{FilePath}, file{new QFile(filePath)}, bytesSent{0}, filesize{0}, + status{STOPPED}, direction{Direction}, sendTimer{nullptr} { } diff --git a/src/core/corestructs.h b/src/core/corestructs.h index d6bc81ae3..fc16c852e 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -67,13 +67,14 @@ struct ToxFile void setFilePath(QString path); bool open(bool write); + uint8_t fileKind; ///< Data file (default) or avatar uint32_t fileNum; uint32_t friendId; QByteArray fileName; QString filePath; QFile* file; - qint64 bytesSent; - qint64 filesize; + quint64 bytesSent; + quint64 filesize; FileStatus status; FileDirection direction; QTimer* sendTimer; diff --git a/src/ipc.cpp b/src/ipc.cpp index 8609c9a12..222de3e0a 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -134,6 +134,7 @@ bool IPC::isCurrentOwner() { if (globalMemory.lock()) { + /// TODO: Segfault on exit on "mov rdx,QWORD PTR [rax]" w/ rax=0. bool isOwner = ((*(uint64_t*)globalMemory.data()) == globalId); globalMemory.unlock(); return isOwner;