From 9c66032fdc937f852771949c4b4c94ade67324d8 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Tue, 6 Jan 2015 09:41:17 +0000 Subject: Tox: - fixed file transfer with size > 2mb - fixed file lock after transfer - accelerated file transfers git-svn-id: http://svn.miranda-ng.org/main/trunk@11778 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/src/common.h | 2 + protocols/Tox/src/tox_account.cpp | 8 ++-- protocols/Tox/src/tox_proto.cpp | 2 + protocols/Tox/src/tox_proto.h | 7 +++- protocols/Tox/src/tox_transfer.cpp | 82 +++++++++++++++++++++++++++----------- 5 files changed, 74 insertions(+), 27 deletions(-) (limited to 'protocols/Tox/src') diff --git a/protocols/Tox/src/common.h b/protocols/Tox/src/common.h index 7c5e3a71fc..2bdfc3a657 100644 --- a/protocols/Tox/src/common.h +++ b/protocols/Tox/src/common.h @@ -52,6 +52,8 @@ extern HINSTANCE g_hInstance; #define TOX_DB_EVENT_TYPE_ACTION 10001 +#define TOX_FILE_BLOCK_SIZE 1024 * 1024 + extern HMODULE g_hToxLibrary; template diff --git a/protocols/Tox/src/tox_account.cpp b/protocols/Tox/src/tox_account.cpp index d57b7faf2c..9e74f07a17 100644 --- a/protocols/Tox/src/tox_account.cpp +++ b/protocols/Tox/src/tox_account.cpp @@ -128,9 +128,11 @@ void CToxProto::DoBootstrap() void CToxProto::DoTox() { - mir_cslock lck(toxLock); - - tox_do(tox); + { + mir_cslock lck(toxLock); + tox_do(tox); + } + PulseEvent(hToxEvent); uint32_t interval = tox_do_interval(tox); Sleep(interval); } diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp index f3785a3893..7986987fe4 100644 --- a/protocols/Tox/src/tox_proto.cpp +++ b/protocols/Tox/src/tox_proto.cpp @@ -44,6 +44,8 @@ CToxProto::CToxProto(const char* protoName, const TCHAR* userName) : CreateProtoService(PS_GETAVATARINFOT, &CToxProto::GetAvatarInfo); CreateProtoService(PS_GETMYAVATART, &CToxProto::GetMyAvatar); CreateProtoService(PS_SETMYAVATART, &CToxProto::SetMyAvatar); + + hToxEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } CToxProto::~CToxProto() diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h index d7937fdfc1..2565ceb70d 100644 --- a/protocols/Tox/src/tox_proto.h +++ b/protocols/Tox/src/tox_proto.h @@ -4,11 +4,15 @@ struct FileTransferParam { PROTOFILETRANSFERSTATUS pfts; + bool isTerminated; + FILE *hFile; int number; FileTransferParam(int fileNumber, const TCHAR* fileName, size_t fileSize) { + isTerminated = false; number = fileNumber; + hFile = NULL; pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS); pfts.flags = PFTS_TCHAR; @@ -34,6 +38,7 @@ struct FileTransferParam ~FileTransferParam() { + isTerminated = true; if (pfts.tszWorkingDir != NULL) { mir_free(pfts.tszWorkingDir); @@ -112,7 +117,7 @@ private: Tox *tox; mir_cs toxLock; TCHAR *accountName; - HANDLE hNetlib, hPollingThread; + HANDLE hNetlib, hPollingThread, hToxEvent; bool isTerminated, isConnected; std::map transfers; diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp index c70ce44b60..127c0340af 100644 --- a/protocols/Tox/src/tox_transfer.cpp +++ b/protocols/Tox/src/tox_transfer.cpp @@ -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; @@ -70,6 +70,7 @@ HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const P if (!ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, (HANDLE)transfer, (LPARAM)&transfer->pfts)) { + transfer->hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("ab")); tox_file_send_control(tox, number, 1, transfer->number, TOX_FILECONTROL_ACCEPT, NULL, 0); } @@ -77,7 +78,7 @@ 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) +int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename) { FileTransferParam *transfer = (FileTransferParam*)hTransfer; @@ -90,23 +91,28 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR 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); break; case FILERESUME_OVERWRITE: // truncate file to zero - fclose(_tfopen(transfer->pfts.tszCurrentFile, _T("w+"))); + 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); break; case FILERESUME_SKIP: // deny file request - tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); 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; 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); break; } @@ -122,17 +128,20 @@ void CToxProto::OnFileData(Tox *tox, int32_t number, uint8_t fileNumber, const u MCONTACT hContact = proto->FindContact(number); if (hContact) { + //mir_cslock lck(proto->toxLock); + FileTransferParam *transfer = proto->transfers.at(fileNumber); - FILE *hFile = _tfopen(transfer->pfts.tszCurrentFile, _T("ab")); - if (hFile != NULL) + if (transfer->hFile == NULL) { - if (fwrite(data, sizeof(uint8_t), size, hFile) == size) - { - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); - } - fclose(hFile); + tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + } + + 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); } } } @@ -207,29 +216,50 @@ void CToxProto::SendFileAsync(void* arg) } size_t chunkSize = min(fileSize, (size_t)tox_file_data_size(tox, number)); - uint8_t *data = (uint8_t*)mir_alloc(chunkSize); - while (!feof(hFile) && fileProgress < fileSize) + uint8_t *data = (uint8_t*)mir_alloc(TOX_FILE_BLOCK_SIZE); + while (!feof(hFile) && fileProgress < fileSize && !transfer->isTerminated) { - size_t size = min(chunkSize, fileSize - fileProgress); - if (fread(data, sizeof(uint8_t), size, hFile) != size) + // read file by block of 1mb + size_t blockSize = min(chunkSize * (TOX_FILE_BLOCK_SIZE / chunkSize), fileSize - fileProgress); + if (fread(data, sizeof(uint8_t), blockSize, hFile) != blockSize) { + fclose(hFile); 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; } - while (tox_file_send_data(tox, number, transfer->number, data, size) == TOX_ERROR) + // send block by chunk of chunkSize + size_t blockProgress = 0; + while (blockProgress < blockSize && !transfer->isTerminated) { - Sleep(50); + 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); } - - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += size; - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); } + fclose(hFile); mir_free(data); - uint8_t receive_send = transfer->GetTransferStatus(); - tox_file_send_control(tox, number, receive_send, transfer->number, TOX_FILECONTROL_FINISHED, NULL, 0); + if (!transfer->isTerminated) + { + uint8_t receive_send = transfer->GetTransferStatus(); + tox_file_send_control(tox, number, receive_send, transfer->number, TOX_FILECONTROL_FINISHED, NULL, 0); + } } } @@ -244,6 +274,7 @@ int __cdecl CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) FileTransferParam *transfer = (FileTransferParam*)hTransfer; + transfer->isTerminated = true; tox_file_send_control(tox, number, transfer->GetTransferStatus(), transfer->number, TOX_FILECONTROL_KILL, NULL, 0); RemoveFromTransferList(transfer); @@ -277,6 +308,7 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t number, uint8_t receive_send, ui // if file transfer is cancelled case TOX_FILECONTROL_KILL: + transfer->isTerminated = true; proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); proto->RemoveFromTransferList(transfer); break; @@ -287,6 +319,10 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t number, uint8_t receive_send, ui { tox_file_send_control(proto->tox, number, 1, fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); } + if (transfer->hFile) + { + fclose(transfer->hFile); + } proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)transfer, 0); proto->RemoveFromTransferList(transfer); break; -- cgit v1.2.3