From beaf93e92827b7bcc77c9f6b2a0c7097d355151c Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Fri, 29 Aug 2014 22:11:08 +0000 Subject: Tox: added files receiving git-svn-id: http://svn.miranda-ng.org/main/trunk@10339 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/src/common.h | 1 + protocols/Tox/src/file_transfer.h | 86 ++++++++++++++++++++++++++++--------- protocols/Tox/src/tox_account.cpp | 2 + protocols/Tox/src/tox_events.cpp | 73 ++++++++++++++++++++++++++++++- protocols/Tox/src/tox_proto.cpp | 52 ++++++++++++++++++---- protocols/Tox/src/tox_proto.h | 48 ++++++++++++++++++--- protocols/Tox/src/tox_transfers.cpp | 31 ++++++++++--- 7 files changed, 250 insertions(+), 43 deletions(-) (limited to 'protocols/Tox') diff --git a/protocols/Tox/src/common.h b/protocols/Tox/src/common.h index 545600d409..bb417850ca 100644 --- a/protocols/Tox/src/common.h +++ b/protocols/Tox/src/common.h @@ -10,6 +10,7 @@ #include #include #include +#include #include diff --git a/protocols/Tox/src/file_transfer.h b/protocols/Tox/src/file_transfer.h index d131802973..6f30b90241 100644 --- a/protocols/Tox/src/file_transfer.h +++ b/protocols/Tox/src/file_transfer.h @@ -6,16 +6,16 @@ class CFileTransfer; class CFile { private: - HANDLE hProcess; - - const CFileTransfer *transfer; - + int number; char *name; const TCHAR *path; size_t size; + const CFileTransfer *transfer; + public: - CFile(const CFileTransfer *fileTransfer, const TCHAR *filePath, size_t fileSize) + CFile(const CFileTransfer *fileTransfer, const TCHAR *filePath, size_t fileSize) : + number(-1) { transfer = fileTransfer; @@ -24,14 +24,25 @@ public: size = fileSize; } + CFile(int number) : number(number), name(NULL) { } + ~CFile() { - mir_free(name); + number = -1; + if (name != NULL) + { + mir_free(name); + } + } + + const CFileTransfer *GetTransfer() const + { + return this->transfer; } - void SetHandle(HANDLE hFileProcess) + void SetNumber(int fileNumber) { - hProcess = hFileProcess; + number = fileNumber; } const TCHAR* GetPath() const @@ -53,15 +64,19 @@ public: class CFileTransfer { private: - HANDLE hProcess; - LIST files; + ULONG number; -public: + HANDLE hWait; + LIST files; PROTOFILETRANSFERSTATUS pfts; + const PROTO_INTERFACE *proto; - CFileTransfer(MCONTACT hContact, ULONG hProcess, DWORD flags) : - files(1) +public: + CFileTransfer(const PROTO_INTERFACE *proto, MCONTACT hContact, ULONG transferNumber, DWORD flags) : + files(1, NumericKeySortT) { + this->proto = proto; + pfts.cbSize = sizeof(pfts); pfts.flags = PFTS_TCHAR | flags; pfts.hContact = hContact; @@ -75,7 +90,7 @@ public: pfts.tszWorkingDir = NULL; pfts.tszCurrentFile = NULL; - this->hProcess = (HANDLE)hProcess; + number = transferNumber; } ~CFileTransfer() @@ -120,30 +135,61 @@ public: fclose(file); } - files.insert(new CFile(this, pfts.ptszFiles[i], fileSize)); + files.insert(new CFile(this, ppszFiles[i], fileSize)); } } + const PROTO_INTERFACE *GetProtoInstance() const + { + return proto; + } + + ULONG GetTransferNumber() const + { + return number; + } + + MCONTACT GetContactHandle() const + { + return pfts.hContact; + } + int GetFileCount() const { - return files.getCount(); + return pfts.totalFiles; } - CFile * const GetFileAt(int idx) const + CFile *GetFileAt(int idx) const { return files[idx]; } - HANDLE GetTransferHandler() const + CFile *GetFileByNumber(int number) const + { + CFile *search = new CFile(number); + CFile *file = files.find(search); + delete search; + + return file; + } + + bool HasFile(int number) const + { + const CFile *file = GetFileByNumber(number); + + return file != NULL; + } + + void Wait() { - return hProcess; + WaitForSingleObject(hWait, INFINITE); } }; class CFileSendTransfer : public CFileTransfer { public: - CFileSendTransfer(MCONTACT hContact, ULONG hProcess) : CFileTransfer(hContact, hProcess, PFTS_SENDING) + CFileSendTransfer(MCONTACT hContact, ULONG hProcess) : CFileTransfer(NULL, hContact, hProcess, PFTS_SENDING) { } }; diff --git a/protocols/Tox/src/tox_account.cpp b/protocols/Tox/src/tox_account.cpp index 7ab6038480..886bf70f7b 100644 --- a/protocols/Tox/src/tox_account.cpp +++ b/protocols/Tox/src/tox_account.cpp @@ -35,6 +35,8 @@ void CToxProto::InitToxCore() tox_callback_read_receipt(tox, OnReadReceipt, this); tox_callback_connection_status(tox, OnConnectionStatusChanged, this); tox_callback_file_control(tox, OnFileRequest, this); + tox_callback_file_send_request(tox, OnFriendFile, this); + tox_callback_file_data(tox, OnFileData, this); LoadToxData(); diff --git a/protocols/Tox/src/tox_events.cpp b/protocols/Tox/src/tox_events.cpp index a133b17e35..1a27e498ef 100644 --- a/protocols/Tox/src/tox_events.cpp +++ b/protocols/Tox/src/tox_events.cpp @@ -124,7 +124,7 @@ int CToxProto::OnPreCreateMessage(WPARAM wParam, LPARAM lParam) char *message = (char*)evt->dbei->pBlob; if (strncmp(message, "/me ", 4) == 0) { - BYTE *action = (BYTE*)mir_alloc(sizeof(BYTE) * (evt->dbei->cbBlob - 4)); + BYTE *action = (BYTE*)mir_alloc(sizeof(BYTE)* (evt->dbei->cbBlob - 4)); memcpy(action, (char*)&evt->dbei->pBlob[4], evt->dbei->cbBlob - 4); mir_free(evt->dbei->pBlob); evt->dbei->pBlob = action; @@ -256,14 +256,83 @@ void CToxProto::OnReadReceipt(Tox *tox, int32_t number, uint32_t receipt, void * } } +void CToxProto::OnFriendFile(Tox *tox, int32_t number, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg) +{ + CToxProto *proto = (CToxProto*)arg; + + MCONTACT hContact = proto->FindContact(number); + if (hContact) + { + FileTransferParam *transfer = new FileTransferParam(fileNumber, ptrT(mir_utf8decodeT((const char*)fileName)), fileSize); + transfer->pfts.hContact = hContact; + transfer->pfts.flags |= PFTS_RECEIVING; + proto->transfers[fileNumber] = transfer; + + PROTORECVFILET pre = { 0 }; + pre.flags = PREF_TCHAR; + pre.fileCount = 1; + pre.timestamp = time(NULL); + pre.tszDescription = _T(""); + pre.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)* 2); + pre.ptszFiles[0] = mir_utf8decodeT((char*)fileName); + pre.ptszFiles[1] = NULL; + pre.lParam = (LPARAM)fileNumber; + ProtoChainRecvFile(hContact, &pre); + } +} + +void CToxProto::OnFileData(Tox *tox, int32_t number, uint8_t fileNumber, const uint8_t *data, uint16_t size, void *arg) +{ + CToxProto *proto = (CToxProto*)arg; + + MCONTACT hContact = proto->FindContact(number); + if (hContact) + { + FileTransferParam *transfer = proto->transfers.at(fileNumber); + + TCHAR filePath[MAX_PATH]; + mir_sntprintf(filePath, SIZEOF(filePath), _T("%s%s"), transfer->pfts.tszWorkingDir, transfer->pfts.tszCurrentFile); + + FILE *hFile = NULL; + if (transfer->pfts.currentFileProgress == 0) + { + hFile = _tfopen(filePath, _T("wb")); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)fileNumber, 0); + } + else + { + hFile = _tfopen(filePath, _T("ab")); + } + if (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)fileNumber, (LPARAM)&transfer->pfts); + } + fclose(hFile); + } + } +} + void CToxProto::OnFileRequest(Tox *tox, int32_t number, uint8_t isSend, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; + MCONTACT hContact = proto->FindContact(number); if (hContact) { - if (isSend && type == TOX_FILECONTROL_ACCEPT) + FileTransferParam *transfer = proto->transfers.at(fileNumber); + + switch (type) { + case TOX_FILECONTROL_ACCEPT: + break; + + case TOX_FILECONTROL_FINISHED: + tox_file_send_control(proto->tox, number, 1, fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)fileNumber, 0); + break; } } } \ No newline at end of file diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp index 3693cfc741..5734700a99 100644 --- a/protocols/Tox/src/tox_proto.cpp +++ b/protocols/Tox/src/tox_proto.cpp @@ -2,7 +2,7 @@ CToxProto::CToxProto(const char* protoName, const TCHAR* userName) : PROTO(protoName, userName), - fileSendQueue(1, NumericKeySortT), + fileTransfers(1, NumericKeySortT), hFileProcess(0) { InitToxCore(); @@ -51,11 +51,11 @@ DWORD_PTR __cdecl CToxProto::GetCaps(int type, MCONTACT hContact) switch (type) { case PFLAGNUM_1: - return PF1_IM | PF1_AUTHREQ | PF1_EXTSEARCH; + return PF1_IM | PF1_FILERECV | PF1_AUTHREQ | PF1_EXTSEARCH; case PFLAGNUM_2: return PF2_ONLINE | PF2_SHORTAWAY | PF2_LIGHTDND; case PFLAGNUM_4: - return PF4_IMSENDUTF | PF4_NOAUTHDENYREASON | PF4_FORCEAUTH | PF4_FORCEADDED | PF4_SUPPORTTYPING; + return PF4_IMSENDUTF | PF4_SINGLEFILEONLY | PF4_NOAUTHDENYREASON | PF4_FORCEAUTH | PF4_FORCEADDED | PF4_SUPPORTTYPING; case PFLAG_UNIQUEIDTEXT: return (INT_PTR)"Tox ID"; case PFLAG_UNIQUEIDSETTING: @@ -142,9 +142,41 @@ int __cdecl CToxProto::AuthRequest(MCONTACT hContact, const PROTOCHAR* szMessage HANDLE __cdecl CToxProto::ChangeInfo(int iInfoType, void* pInfoData) { return 0; } -HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath) { return 0; } -int __cdecl CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) { return 0; } -int __cdecl CToxProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason) { return 0; } +HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszPath) +{ + std::string toxId(getStringA(hContact, TOX_SETTINGS_ID)); + std::vector clientId = HexStringToData(toxId); + + uint32_t number = tox_get_friend_number(tox, clientId.data()); + uint8_t fileNumber = (uint8_t)hTransfer; + + transfers.at(fileNumber)->pfts.tszWorkingDir = mir_tstrdup(tszPath); + + tox_file_send_control(tox, number, 1, fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0); + + return hTransfer; +} + +int __cdecl CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) +{ + std::string toxId(getStringA(hContact, TOX_SETTINGS_ID)); + std::vector clientId = HexStringToData(toxId); + + uint32_t number = tox_get_friend_number(tox, clientId.data()); + uint8_t fileNumber = (uint8_t)hTransfer; + + transfers.erase(fileNumber); + + int result = tox_file_send_control(tox, number, 1, fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + + return result + 1; +} + +int __cdecl CToxProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR*) +{ + return FileCancel(hContact, hTransfer); +} + int __cdecl CToxProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename) { return 0; } int __cdecl CToxProto::GetInfo(MCONTACT hContact, int infoType) { return 0; } @@ -216,7 +248,11 @@ HWND __cdecl CToxProto::CreateExtendedSearchUI(HWND owner) } int __cdecl CToxProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT*) { return 0; } -int __cdecl CToxProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT*) { return 0; } + +int __cdecl CToxProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT *pre) +{ + return Proto_RecvFile(hContact, pre); +} int __cdecl CToxProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) { @@ -234,7 +270,7 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescrip ForkThread(&CToxProto::SendFilesAsync, transfer); - return transfer->GetTransferHandler(); + return (HANDLE)transfer->GetTransferNumber(); } int __cdecl CToxProto::SendMsg(MCONTACT hContact, int flags, const char* msg) diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h index c910317abb..81d03f952c 100644 --- a/protocols/Tox/src/tox_proto.h +++ b/protocols/Tox/src/tox_proto.h @@ -1,7 +1,38 @@ #ifndef _TOX_PROTO_H_ #define _TOX_PROTO_H_ -class CFile; +class CFileTransfer; + +struct FileTransferParam +{ + PROTOFILETRANSFERSTATUS pfts; + uint8_t number; + + FileTransferParam(uint8_t number, const TCHAR* fileName, size_t fileSize) + { + pfts = { sizeof(PROTOFILETRANSFERSTATUS) }; + pfts.flags = PFTS_TCHAR; + pfts.totalFiles = 1; + pfts.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)*(pfts.totalFiles + 1)); + pfts.ptszFiles[0] = pfts.tszCurrentFile = mir_tstrdup(fileName); + pfts.ptszFiles[pfts.totalFiles] = NULL; + pfts.totalBytes = pfts.currentFileSize = fileSize; + pfts.totalProgress = pfts.currentFileProgress = 0; + pfts.currentFileNumber = 0; + pfts.tszWorkingDir = NULL; + } + + ~FileTransferParam() + { + if (pfts.tszWorkingDir != NULL) + { + mir_free(pfts.tszWorkingDir); + } + + mir_free(pfts.pszFiles[0]); + mir_free(pfts.pszFiles); + } +}; struct CToxProto : public PROTO { @@ -26,10 +57,10 @@ public: virtual HANDLE __cdecl ChangeInfo(int iInfoType, void* pInfoData); - virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath); + virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszPath); virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer); - virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szReason); - virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename); + virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* tszReason); + virtual int __cdecl FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** tszFilename); virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL); virtual int __cdecl GetInfo(MCONTACT hContact, int infoType); @@ -76,7 +107,8 @@ private: bool isConnected; HANDLE hNetlibUser; ULONG hFileProcess; - LIST fileSendQueue; + LIST fileTransfers; + std::map transfers; // tox void InitToxCore(); @@ -122,6 +154,8 @@ private: //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 isSend, 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); // contacts WORD GetContactStatus(MCONTACT hContact); @@ -141,9 +175,11 @@ private: void __cdecl SearchByNameAsync(void* arg); // file transfer - static int FileSendQueueCompare(const CFile* p1, const CFile* p2); + void __cdecl SendFileAsync(void* arg); void __cdecl SendFilesAsync(void* arg); + CFileTransfer *GetFileTransferByFileNumber(int fileNumber); + // utils TOX_USERSTATUS MirandaToToxStatus(int status); int ToxToMirandaStatus(TOX_USERSTATUS userstatus); diff --git a/protocols/Tox/src/tox_transfers.cpp b/protocols/Tox/src/tox_transfers.cpp index b15ac1838f..51bab8aac3 100644 --- a/protocols/Tox/src/tox_transfers.cpp +++ b/protocols/Tox/src/tox_transfers.cpp @@ -1,27 +1,44 @@ #include "common.h" -int CToxProto::FileSendQueueCompare(const CFile* p1, const CFile* p2) +void CToxProto::SendFileAsync(void* arg) { - return 0; + CFile *file = (CFile*)arg; + const CFileTransfer *transfer = file->GetTransfer(); + CToxProto *proto = (CToxProto*)transfer->GetProtoInstance(); } void CToxProto::SendFilesAsync(void* arg) { - CFileTransfer *ftp = (CFileTransfer*)arg; + CFileTransfer *transfer = (CFileTransfer*)arg; - std::string toxId(getStringA(ftp->pfts.hContact, TOX_SETTINGS_ID)); + std::string toxId(getStringA(transfer->GetContactHandle(), TOX_SETTINGS_ID)); std::vector clientId = HexStringToData(toxId); uint32_t number = tox_get_friend_number(tox, clientId.data()); - for (int i = 0; ftp->GetFileCount(); i++) + for (int i = 0; transfer->GetFileCount(); i++) { - CFile *file = ftp->GetFileAt(i); + CFile *file = transfer->GetFileAt(i); + int hFile = tox_new_file_sender(tox, number, file->GetSize(), (uint8_t*)file->GetName(), strlen(file->GetName())); if (hFile < 0) { debugLogA("CToxProto::SendFilesAsync: cannot send file"); } - file->SetHandle((HANDLE)hFile); + file->SetNumber(hFile); + + transfer->Wait(); + } +} + +CFileTransfer *CToxProto::GetFileTransferByFileNumber(int fileNumber) +{ + for (int i = 0; fileTransfers.getCount(); i++) + { + if (fileTransfers[i]->HasFile(fileNumber)) + { + return fileTransfers[i]; + } } + return NULL; } \ No newline at end of file -- cgit v1.2.3