From a8af35bf6e3de34405ce5dbc3b035039a9ee4806 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 18 Jan 2015 22:45:37 +0000 Subject: Tox: - added pause support for file sending - added resuming for broken file transfers - updated tox core git-svn-id: http://svn.miranda-ng.org/main/trunk@11875 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/src/tox_account.cpp | 8 +- protocols/Tox/src/tox_contacts.cpp | 41 +++++-- protocols/Tox/src/tox_messages.cpp | 4 +- protocols/Tox/src/tox_proto.cpp | 2 +- protocols/Tox/src/tox_proto.h | 83 ++++++++++--- protocols/Tox/src/tox_transfer.cpp | 231 ++++++++++++++++++++----------------- 6 files changed, 225 insertions(+), 144 deletions(-) (limited to 'protocols/Tox/src') diff --git a/protocols/Tox/src/tox_account.cpp b/protocols/Tox/src/tox_account.cpp index 5c4154af29..3b4f61b32b 100644 --- a/protocols/Tox/src/tox_account.cpp +++ b/protocols/Tox/src/tox_account.cpp @@ -142,11 +142,9 @@ void CToxProto::DoBootstrap() void CToxProto::DoTox() { - { - mir_cslock lock(toxLock); - tox_do(tox); - } - PulseEvent(hToxEvent); + tox_do(tox); + + //PulseEvent(hToxEvent); uint32_t interval = tox_do_interval(tox); Sleep(interval); } diff --git a/protocols/Tox/src/tox_contacts.cpp b/protocols/Tox/src/tox_contacts.cpp index 6a7321546f..5cd56e099d 100644 --- a/protocols/Tox/src/tox_contacts.cpp +++ b/protocols/Tox/src/tox_contacts.cpp @@ -73,7 +73,7 @@ MCONTACT CToxProto::FindContact(const std::string &id) } db_free(&dbv); - if (_strnicmp(id.c_str(), clientId.c_str(), TOX_CLIENT_ID_SIZE) == 0) + if (mir_strcmpi(id.c_str(), clientId.c_str()) == 0) { break; } @@ -221,22 +221,22 @@ void CToxProto::OnFriendRequest(Tox *tox, const uint8_t *address, const uint8_t ProtoChainRecv(hContact, PSR_AUTH, 0, (LPARAM)&pre); } -void CToxProto::OnFriendNameChange(Tox *tox, const int number, const uint8_t *name, const uint16_t nameSize, void *arg) +void CToxProto::OnFriendNameChange(Tox *tox, const int friendNumber, const uint8_t *name, const uint16_t nameSize, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { proto->setString(hContact, "Nick", (char*)name); } } -void CToxProto::OnStatusMessageChanged(Tox *tox, const int number, const uint8_t* message, const uint16_t messageSize, void *arg) +void CToxProto::OnStatusMessageChanged(Tox *tox, const int friendNumber, const uint8_t* message, const uint16_t messageSize, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { ptrW statusMessage(mir_utf8decodeW((char*)message)); @@ -244,11 +244,11 @@ void CToxProto::OnStatusMessageChanged(Tox *tox, const int number, const uint8_t } } -void CToxProto::OnUserStatusChanged(Tox *tox, int32_t number, uint8_t usertatus, void *arg) +void CToxProto::OnUserStatusChanged(Tox *tox, int32_t friendNumber, uint8_t usertatus, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { TOX_USERSTATUS userstatus = (TOX_USERSTATUS)usertatus; @@ -257,19 +257,40 @@ void CToxProto::OnUserStatusChanged(Tox *tox, int32_t number, uint8_t usertatus, } } -void CToxProto::OnConnectionStatusChanged(Tox *tox, const int number, const uint8_t status, void *arg) +void CToxProto::OnConnectionStatusChanged(Tox *tox, const int friendNumber, const uint8_t status, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + //mir_cslock lock(proto->toxLock); + + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { int newStatus = status ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; proto->SetContactStatus(hContact, newStatus); if (status) { - tox_send_avatar_info(proto->tox, number); + tox_send_avatar_info(proto->tox, friendNumber); proto->delSetting(hContact, "Auth"); + + for (std::map::iterator it = proto->transfers.begin(); it != proto->transfers.end(); it++) + { + // only for receiving + if (it->second->friendNumber == friendNumber && it->second->GetDirection() == 1) + { + it->second->Broken(tox); + } + } + } + else + { + for (std::map::iterator it = proto->transfers.begin(); it != proto->transfers.end(); it++) + { + if (it->second->friendNumber == friendNumber) + { + it->second->status = PAUSED; + } + } } } } diff --git a/protocols/Tox/src/tox_messages.cpp b/protocols/Tox/src/tox_messages.cpp index 9926068014..51f255b546 100644 --- a/protocols/Tox/src/tox_messages.cpp +++ b/protocols/Tox/src/tox_messages.cpp @@ -52,13 +52,13 @@ int __cdecl CToxProto::SendMsg(MCONTACT hContact, int flags, const char* msg) } else { - result = tox_send_action(tox, number, (uint8_t*)&msg[4], (uint16_t)strlen(msg) - 4); + result = tox_send_action(tox, number, (uint8_t*)&msg[4], (uint16_t)(strlen(msg) - 4)); } } if (result == 0) { - debugLogA("CToxProto::SendMsg: could not to send message"); + debugLogA("CToxProto::SendMsg: failed to send message"); } return result; diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp index e9d93dac78..b5be241c0f 100644 --- a/protocols/Tox/src/tox_proto.cpp +++ b/protocols/Tox/src/tox_proto.cpp @@ -253,7 +253,7 @@ int __cdecl CToxProto::SetAwayMsg(int iStatus, const PROTOCHAR *msg) { if (IsOnline()) { - WaitForSingleObject(hToxEvent, INFINITE); + //WaitForSingleObject(hToxEvent, INFINITE); ptrA statusMessage(msg == NULL ? mir_strdup("") : mir_utf8encodeT(msg)); if (tox_set_status_message(tox, (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUSMESSAGE_LENGTH, strlen(statusMessage))) == TOX_ERROR) diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h index 962af5b609..92ba5ba49d 100644 --- a/protocols/Tox/src/tox_proto.h +++ b/protocols/Tox/src/tox_proto.h @@ -1,18 +1,31 @@ #ifndef _TOX_PROTO_H_ #define _TOX_PROTO_H_ +enum FILE_TRANSFER_STATUS +{ + NONE, + STARTED, + PAUSED, + FAILED, + CANCELED, + FINISHED, + DESTROYED +}; + struct FileTransferParam { PROTOFILETRANSFERSTATUS pfts; - bool isTerminated; + FILE_TRANSFER_STATUS status; FILE *hFile; - int number; + int friendNumber; + int fileNumber; - FileTransferParam(int fileNumber, const TCHAR* fileName, size_t fileSize) + FileTransferParam(int friendNumber, int fileNumber, const TCHAR* fileName, size_t fileSize) { - isTerminated = false; - number = fileNumber; + status = NONE; hFile = NULL; + this->friendNumber = friendNumber; + this->fileNumber = fileNumber; pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.flags = PFTS_TCHAR; @@ -26,19 +39,55 @@ struct FileTransferParam pfts.tszWorkingDir = NULL; } - void ChangeFileName(const TCHAR* fileName) + bool OpenFile(const TCHAR *mode) + { + hFile = _tfopen(pfts.tszCurrentFile, mode); + return hFile != NULL; + } + + void Start(Tox *tox) + { + status = STARTED; + tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0); + } + + void Broken(Tox *tox) + { + status = PAUSED; + tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_RESUME_BROKEN, (uint8_t*)&pfts.currentFileProgress, sizeof(uint64_t)); + } + + void Fail(Tox *tox) + { + status = FAILED; + tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + } + + void Cancel(Tox *tox) + { + status = FINISHED; + tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + } + + void Finish(Tox *tox) + { + status = FINISHED; + tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); + } + + void RenameName(const TCHAR* fileName) { pfts.ptszFiles[0] = replaceStrT(pfts.tszCurrentFile, fileName); } - uint8_t GetTransferStatus() const + uint8_t GetDirection() const { return pfts.flags & PFTS_SENDING ? 0 : 1; } ~FileTransferParam() { - isTerminated = true; + status = DESTROYED; if (pfts.tszWorkingDir != NULL) { mir_free(pfts.tszWorkingDir); @@ -94,8 +143,8 @@ public: virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*); virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*); - virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT* hContactsList); - virtual HANDLE __cdecl SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles); + virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList); + virtual HANDLE __cdecl SendFile(MCONTACT hContact, const PROTOCHAR *szDescription, PROTOCHAR **ppszFiles); virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg); virtual int __cdecl SendUrl(MCONTACT hContact, int flags, const char* url); @@ -182,10 +231,10 @@ private: int __cdecl OnContactDeleted(MCONTACT, LPARAM); static void OnFriendRequest(Tox *tox, const uint8_t *address, const uint8_t *message, const uint16_t messageSize, void *arg); - static void OnFriendNameChange(Tox *tox, const int number, const uint8_t *name, const uint16_t nameSize, void *arg); - static void OnStatusMessageChanged(Tox *tox, const int number, const uint8_t* message, const uint16_t messageSize, void *arg); - static void OnUserStatusChanged(Tox *tox, int32_t number, uint8_t usertatus, void *arg); - static void OnConnectionStatusChanged(Tox *tox, const int number, const uint8_t status, void *arg); + static void OnFriendNameChange(Tox *tox, const int friendNumber, const uint8_t *name, const uint16_t nameSize, void *arg); + static void OnStatusMessageChanged(Tox *tox, const int friendNumber, const uint8_t* message, const uint16_t messageSize, void *arg); + static void OnUserStatusChanged(Tox *tox, int32_t friendNumber, uint8_t usertatus, void *arg); + static void OnConnectionStatusChanged(Tox *tox, const int friendNumber, const uint8_t status, void *arg); // contacts search void __cdecl SearchFailedAsync(void* arg); @@ -208,9 +257,9 @@ private: void __cdecl SendFileAsync(void* arg); //static void OnFileControlCallback(Tox *tox, int32_t number, uint8_t hFile, uint64_t fileSize, uint8_t *name, uint16_t nameSize, void *arg); - static void OnFileRequest(Tox *tox, int32_t number, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg); - static void OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg); - static void OnFileData(Tox *tox, int32_t number, uint8_t fileNumber, const uint8_t *data, uint16_t length, void *arg); + static void OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg); + static void OnFriendFile(Tox *tox, int32_t friendNumber, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg); + static void OnFileData(Tox *tox, int32_t friendNumber, uint8_t fileNumber, const uint8_t *data, uint16_t length, void *arg); // avatars std::tstring GetAvatarFilePath(MCONTACT hContact = NULL); diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp index 22af0bb711..3ff4a9a0e1 100644 --- a/protocols/Tox/src/tox_transfer.cpp +++ b/protocols/Tox/src/tox_transfer.cpp @@ -2,17 +2,17 @@ void CToxProto::AddToTransferList(FileTransferParam *transfer) { - if (transfers.find(transfer->number) == transfers.end()) + if (transfers.find(transfer->fileNumber) == transfers.end()) { - transfers[transfer->number] = transfer; + transfers[transfer->fileNumber] = transfer; } } void CToxProto::RemoveFromTransferList(FileTransferParam *transfer) { - if (transfers.find(transfer->number) != transfers.end()) + if (transfers.find(transfer->fileNumber) != transfers.end()) { - transfers.erase(transfer->number); + transfers.erase(transfer->fileNumber); delete transfer; } } @@ -21,11 +21,11 @@ void CToxProto::RemoveFromTransferList(FileTransferParam *transfer) // incoming file flow // send it through miranda -void CToxProto::OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg) +void CToxProto::OnFriendFile(Tox *tox, int32_t friendNumber, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { TCHAR *name = mir_utf8decodeT((char*)fileName); @@ -35,7 +35,7 @@ void CToxProto::OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint6 name = mir_a2u((char*)fileName); } - FileTransferParam *transfer = new FileTransferParam(fileNumber, name, fileSize); + FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, name, fileSize); transfer->pfts.hContact = hContact; transfer->pfts.flags |= PFTS_RECEIVING; proto->AddToTransferList(transfer); @@ -45,7 +45,7 @@ void CToxProto::OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint6 pre.fileCount = 1; pre.timestamp = time(NULL); pre.tszDescription = _T(""); - pre.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*) * 2); + pre.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)*2); pre.ptszFiles[0] = name; pre.ptszFiles[1] = NULL; pre.lParam = (LPARAM)transfer; @@ -56,9 +56,9 @@ void CToxProto::OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint6 // file request is allowed HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR *tszPath) { - std::string id = getStringA(hContact, TOX_SETTINGS_ID); + /*std::string id = getStringA(hContact, TOX_SETTINGS_ID); std::vector clientId = HexStringToData(id); - uint32_t number = tox_get_friend_number(tox, clientId.data()); + uint32_t number = tox_get_friend_number(tox, clientId.data());*/ FileTransferParam *transfer = (FileTransferParam*)hTransfer; transfer->pfts.tszWorkingDir = mir_tstrdup(tszPath); @@ -66,12 +66,20 @@ HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const P // stupid fix TCHAR fullPath[MAX_PATH]; mir_sntprintf(fullPath, SIZEOF(fullPath), _T("%s\\%s"), transfer->pfts.tszWorkingDir, transfer->pfts.tszCurrentFile); - transfer->ChangeFileName(fullPath); + transfer->RenameName(fullPath); if (!ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, (HANDLE)transfer, (LPARAM)&transfer->pfts)) { - transfer->hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("wb")); - tox_file_send_control(tox, number, 1, transfer->number, TOX_FILECONTROL_ACCEPT, NULL, 0); + if (!transfer->OpenFile(_T("wb"))) + { + debugLogA("CToxProto::FileAllow: cannot to open file (%d)", transfer->fileNumber); + transfer->Fail(tox); + RemoveFromTransferList(transfer); + return NULL; + } + + debugLogA("CToxProto::FileAllow: start receiving file (%d)", transfer->fileNumber); + transfer->Start(tox); } return hTransfer; @@ -80,67 +88,62 @@ HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const P // if file is exists int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename) { + bool result = false; FileTransferParam *transfer = (FileTransferParam*)hTransfer; - std::string id = getStringA(transfer->pfts.hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - uint32_t number = tox_get_friend_number(tox, clientId.data()); - switch (*action) { case FILERESUME_RENAME: - // rename file - transfer->ChangeFileName(*szFilename); - transfer->hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("wb")); - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_ACCEPT, NULL, 0); + transfer->RenameName(*szFilename); + result = transfer->OpenFile(_T("wb")); break; case FILERESUME_OVERWRITE: - // truncate file to zero - transfer->hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("wb")); - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_ACCEPT, NULL, 0); + result = transfer->OpenFile(_T("wb")); break; case FILERESUME_SKIP: - // deny file request - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); - RemoveFromTransferList(transfer); - break; + result = false; + return 0; case FILERESUME_RESUME: - transfer->hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("ab")); - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_ACCEPT, NULL, 0); + result = transfer->OpenFile(_T("ab")); break; } + if (result) + { + transfer->Start(tox); + } + else + { + transfer->Cancel(tox); + RemoveFromTransferList(transfer); + } + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, result ? ACKRESULT_CONNECTED : ACKRESULT_DENIED, (HANDLE)transfer, 0); + return 0; } // getting the file data -void CToxProto::OnFileData(Tox *tox, int32_t number, uint8_t fileNumber, const uint8_t *data, uint16_t size, void *arg) +void CToxProto::OnFileData(Tox *tox, int32_t friendNumber, uint8_t fileNumber, const uint8_t *data, uint16_t size, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { FileTransferParam *transfer = proto->transfers.at(fileNumber); - if (transfer->hFile == NULL) + if (fwrite(data, sizeof(uint8_t), size, transfer->hFile) != size) { - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); + proto->debugLogA("CToxProto::OnFileData: cannot write to file (%d)", fileNumber); proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + transfer->Fail(tox); } - if (fwrite(data, sizeof(uint8_t), size, transfer->hFile) == size) - { - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); - } + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); } } @@ -148,11 +151,11 @@ void CToxProto::OnFileData(Tox *tox, int32_t number, uint8_t fileNumber, const u // outcoming file flow // send request through tox -HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles) +HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR *szDescription, PROTOCHAR **ppszFiles) { std::string id = getStringA(hContact, TOX_SETTINGS_ID); std::vector clientId = HexStringToData(id); - uint32_t number = tox_get_friend_number(tox, clientId.data()); + uint32_t friendNumber = tox_get_friend_number(tox, clientId.data()); TCHAR *fileName = _tcsrchr(ppszFiles[0], '\\') + 1; @@ -173,14 +176,14 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescrip fseek(hFile, 0, SEEK_SET); char *name = mir_utf8encodeW(fileName); - int fileNumber = tox_new_file_sender(tox, number, fileSize, (uint8_t*)name, strlen(name)); + int fileNumber = tox_new_file_sender(tox, friendNumber, fileSize, (uint8_t*)name, strlen(name)); if (fileNumber < 0) { debugLogA("CToxProto::SendFilesAsync: cannot send file"); return NULL; } - FileTransferParam *transfer = new FileTransferParam(fileNumber, fileName, fileSize); + FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, fileName, fileSize); transfer->pfts.hContact = hContact; transfer->pfts.flags |= PFTS_SENDING; transfer->pfts.tszWorkingDir = fileDir; @@ -191,65 +194,55 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescrip } // start sending -void CToxProto::SendFileAsync(void* arg) +void CToxProto::SendFileAsync(void *arg) { FileTransferParam *transfer = (FileTransferParam*)arg; + transfer->status = STARTED; - std::string id = getStringA(transfer->pfts.hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - int32_t number = tox_get_friend_number(tox, clientId.data()); - if (number > TOX_ERROR) - { - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); + debugLogA("CToxProto::SendFileAsync: start sending file (%d)", transfer->fileNumber); + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); - size_t fileSize = transfer->pfts.currentFileSize; - size_t fileProgress = 0; - TCHAR filePath[MAX_PATH]; - mir_sntprintf(filePath, SIZEOF(filePath), _T("%s%s"), transfer->pfts.tszWorkingDir, transfer->pfts.tszCurrentFile); + size_t fileSize = transfer->pfts.currentFileSize; + size_t fileProgress = 0; + TCHAR filePath[MAX_PATH]; + mir_sntprintf(filePath, SIZEOF(filePath), _T("%s%s"), transfer->pfts.tszWorkingDir, transfer->pfts.tszCurrentFile); - size_t chunkSize = min(fileSize, (size_t)tox_file_data_size(tox, number)); - uint8_t *data = (uint8_t*)mir_alloc(TOX_FILE_BLOCK_SIZE); - while (!feof(transfer->hFile) && fileProgress < fileSize && !transfer->isTerminated) + uint16_t chunkSize = min(fileSize, (size_t)tox_file_data_size(tox, transfer->friendNumber)); + uint8_t *data = (uint8_t*)mir_alloc(chunkSize); + while (transfer->status < FAILED && !feof(transfer->hFile) && fileProgress < fileSize) + { + if (transfer->status == PAUSED) { - // read file by block of TOX_FILE_BLOCK_SIZE - size_t blockSize = min(chunkSize * (TOX_FILE_BLOCK_SIZE / chunkSize), fileSize - fileProgress); - if (fread(data, sizeof(uint8_t), blockSize, transfer->hFile) != blockSize) - { - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); - return; - } + Sleep(1000); + continue; + } - // send block by chunk of chunkSize - size_t blockProgress = 0; - while (blockProgress < blockSize && !transfer->isTerminated) - { - size_t size = min(chunkSize, blockSize - blockProgress); - do - { - { - //mir_cslock lck(toxLock); - - if (tox_file_send_data(tox, number, transfer->number, &data[blockProgress], size) != TOX_ERROR) - { - break; - } - } - WaitForSingleObject(hToxEvent, INFINITE); - } while (!transfer->isTerminated); - - blockProgress += size; - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += size; - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); - } + //mir_cslock lock(toxLock); + + uint16_t size = min(chunkSize, fileSize - fileProgress); + if (fread(data, sizeof(uint8_t), size, transfer->hFile) != size) + { + transfer->Fail(tox); + debugLogA("CToxProto::SendFileAsync: failed to read from file (%d)", transfer->fileNumber); + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + return; } - mir_free(data); - if (!transfer->isTerminated) + if (tox_file_send_data(tox, transfer->friendNumber, transfer->fileNumber, data, size) == TOX_ERROR) { - uint8_t receive_send = transfer->GetTransferStatus(); - tox_file_send_control(tox, number, receive_send, transfer->number, TOX_FILECONTROL_FINISHED, NULL, 0); + fseek(transfer->hFile, -size, SEEK_CUR); + continue; } + + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += size; + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); + } + mir_free(data); + + if (transfer->status == STARTED) + { + //mir_cslock lock(toxLock); + transfer->Finish(tox); } } @@ -258,14 +251,8 @@ void CToxProto::SendFileAsync(void* arg) // file request is cancelled int __cdecl CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) { - std::string id = getStringA(hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - uint32_t number = tox_get_friend_number(tox, clientId.data()); - FileTransferParam *transfer = (FileTransferParam*)hTransfer; - - transfer->isTerminated = true; - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); + transfer->Cancel(tox); RemoveFromTransferList(transfer); return 0; @@ -277,11 +264,13 @@ int __cdecl CToxProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTO return FileCancel(hContact, hTransfer); } -void CToxProto::OnFileRequest(Tox *tox, int32_t number, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg) +void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + //mir_cslock lock(proto->toxLock); + + MCONTACT hContact = proto->FindContact(friendNumber); if (hContact) { FileTransferParam *transfer = proto->transfers.at(fileNumber); @@ -292,22 +281,46 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t number, uint8_t receive_send, ui if (receive_send == 1) { // if friend allow file request - proto->ForkThread(&CToxProto::SendFileAsync, transfer); + if (transfer->status == NONE) + { + proto->ForkThread(&CToxProto::SendFileAsync, transfer); + } + else + { + // unpause file transfer + transfer->status = STARTED; + } + } + break; + + case TOX_FILECONTROL_PAUSE: + transfer->status = PAUSED; + break; + + case TOX_FILECONTROL_RESUME_BROKEN: + // only for sending + if (receive_send == 0) + { + //uint64_t progress = *(uint64_t*)data; + transfer->Start(tox); } break; - // if file transfer is cancelled case TOX_FILECONTROL_KILL: - transfer->isTerminated = true; + transfer->status = CANCELED; proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); proto->RemoveFromTransferList(transfer); break; - // if file transfer is finished case TOX_FILECONTROL_FINISHED: if (receive_send == 0) { - tox_file_send_control(proto->tox, number, 1, fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); + transfer->Finish(tox); + proto->debugLogA("CToxProto::OnFileRequest: finished receiving file (%d)", fileNumber); + } + else + { + proto->debugLogA("CToxProto::OnFileRequest: finished sending file (%d)", fileNumber); } proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)transfer, 0); proto->RemoveFromTransferList(transfer); -- cgit v1.2.3