diff options
author | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:44 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-03-02 12:32:55 +0300 |
commit | 931a7dc1ac0dbc7e6c1083583ced915e572f5b47 (patch) | |
tree | 9fe9a6448d44030e26aa7107ce16044ed413e0d0 /protocols/CloudFile/src/file_transfer.h | |
parent | dd7d9954042254e66e3bbbec7195c6be8b1a0663 (diff) |
all protocols (even virtual ones) moved to the Protocols folder
Diffstat (limited to 'protocols/CloudFile/src/file_transfer.h')
-rw-r--r-- | protocols/CloudFile/src/file_transfer.h | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/protocols/CloudFile/src/file_transfer.h b/protocols/CloudFile/src/file_transfer.h new file mode 100644 index 0000000000..692e717f2e --- /dev/null +++ b/protocols/CloudFile/src/file_transfer.h @@ -0,0 +1,255 @@ +#ifndef _FILE_TRANSFER_H_ +#define _FILE_TRANSFER_H_ + +class FileTransferParam +{ +private: + static ULONG hFileProcess; + + ULONG id; + FILE *hFile; + PROTOFILETRANSFERSTATUS pfts; + + bool isTerminated; + + CMStringW m_serverDirectory; + int m_relativePathStart; + + LIST<char> m_links; + CMStringW m_description; + +public: + FileTransferParam(MCONTACT hContact) + : m_links(1) + { + hFile = NULL; + id = InterlockedIncrement(&hFileProcess); + + isTerminated = false; + + m_relativePathStart = 0; + + pfts.flags = PFTS_UNICODE | PFTS_SENDING; + pfts.hContact = hContact; + pfts.currentFileNumber = -1; + pfts.currentFileProgress = 0; + pfts.currentFileSize = 0; + pfts.currentFileTime = 0; + pfts.totalBytes = 0; + pfts.totalFiles = 0; + pfts.totalProgress = 0; + pfts.pszFiles.w = (wchar_t**)mir_alloc(sizeof(wchar_t*) * (pfts.totalFiles + 1)); + pfts.pszFiles.w[pfts.totalFiles] = NULL; + pfts.szWorkingDir.w = NULL; + pfts.szCurrentFile.w = NULL; + + ProtoBroadcastAck(MODULENAME, pfts.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)id, 0); + } + + ~FileTransferParam() + { + CloseCurrentFile(); + + if (pfts.szWorkingDir.w) + mir_free(pfts.szWorkingDir.w); + + if (pfts.pszFiles.a) { + for (int i = 0; pfts.pszFiles.a[i]; i++) + mir_free(pfts.pszFiles.a[i]); + mir_free(pfts.pszFiles.a); + } + + for (auto &link : m_links) + mir_free(link); + m_links.destroy(); + } + + ULONG GetId() const + { + return id; + } + + MCONTACT GetContact() const + { + return pfts.hContact; + } + + const wchar_t* GetDescription() const + { + return m_description.GetString(); + } + + const char** GetSharedLinks(size_t &count) const + { + count = m_links.getCount(); + return (const char**)m_links.getArray(); + } + + void Terminate() + { + isTerminated = true; + } + + void SetDescription(const wchar_t *description) + { + m_description = description; + } + + void SetWorkingDirectory(const wchar_t *path) + { + m_relativePathStart = wcsrchr(path, '\\') - path + 1; + pfts.szWorkingDir.w = (wchar_t*)mir_calloc(sizeof(wchar_t) * m_relativePathStart); + mir_wstrncpy(pfts.szWorkingDir.w, path, m_relativePathStart); + if (PathIsDirectory(path)) + m_serverDirectory = wcsrchr(path, '\\') + 1; + } + + void SetServerDirectory(const wchar_t *name) + { + if (name) + m_serverDirectory = name; + } + + const wchar_t* GetServerDirectory() const + { + if (m_serverDirectory.IsEmpty()) + return nullptr; + return m_serverDirectory.GetString(); + } + + void AddFile(const wchar_t *path) + { + pfts.pszFiles.w = (wchar_t**)mir_realloc(pfts.pszFiles.w, sizeof(wchar_t*) * (pfts.totalFiles + 2)); + pfts.pszFiles.w[pfts.totalFiles++] = mir_wstrdup(path); + pfts.pszFiles.w[pfts.totalFiles] = NULL; + + FILE *file = _wfopen(path, L"rb"); + if (file != NULL) { + _fseeki64(file, 0, SEEK_END); + pfts.totalBytes += _ftelli64(file); + fclose(file); + } + } + + void AddSharedLink(const char *url) + { + m_links.insert(mir_strdup(url)); + } + + const bool IsCurrentFileInSubDirectory() const + { + const wchar_t *backslash = wcschr(GetCurrentRelativeFilePath(), L'\\'); + return backslash != nullptr; + } + + const wchar_t* GetCurrentFilePath() const + { + return pfts.pszFiles.w[pfts.currentFileNumber]; + } + + const wchar_t* GetCurrentRelativeFilePath() const + { + return &GetCurrentFilePath()[m_relativePathStart]; + } + + const wchar_t* GetCurrentFileName() const + { + return wcsrchr(GetCurrentFilePath(), '\\') + 1; + } + + void OpenCurrentFile() + { + hFile = _wfopen(GetCurrentFilePath(), L"rb"); + if (!hFile) + throw Exception("Unable to open file"); + _fseeki64(hFile, 0, SEEK_END); + pfts.currentFileSize = _ftelli64(hFile); + rewind(hFile); + } + + size_t ReadCurrentFile(void *buffer, size_t count) + { + return fread(buffer, sizeof(char), count, hFile); + } + + void CheckCurrentFile() + { + if (ferror(hFile)) + throw Exception("Error while file sending"); + + if (isTerminated) + throw Exception("Transfer was terminated"); + } + + void CloseCurrentFile() + { + if (hFile != NULL) + { + fclose(hFile); + hFile = NULL; + } + } + + const uint64_t GetCurrentFileSize() const + { + return pfts.currentFileSize; + } + + const size_t GetCurrentFileChunkSize() const + { + size_t chunkSize = 1024 * 1024; + if (pfts.currentFileSize < chunkSize) + chunkSize = min(pfts.currentFileSize, chunkSize / 4); + else if (pfts.currentFileSize > 20 * chunkSize) + chunkSize = chunkSize * 4; + return chunkSize; + } + + void Progress(size_t count) + { + pfts.currentFileProgress += count; + pfts.totalProgress += count; + if (pfts.hContact) + ProtoBroadcastAck(MODULENAME, pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&pfts); + } + + void FirstFile() + { + CloseCurrentFile(); + + pfts.currentFileNumber = 0; + pfts.currentFileProgress = 0; + pfts.szCurrentFile.w = wcsrchr(pfts.pszFiles.w[pfts.currentFileNumber], '\\') + 1; + if (pfts.hContact) + ProtoBroadcastAck(MODULENAME, pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)id, (LPARAM)&pfts); + + OpenCurrentFile(); + CheckCurrentFile(); + } + + bool NextFile() + { + CloseCurrentFile(); + + if (++pfts.currentFileNumber == pfts.totalFiles) + return false; + + pfts.currentFileProgress = 0; + pfts.szCurrentFile.w = wcsrchr(pfts.pszFiles.w[pfts.currentFileNumber], '\\') + 1; + if (pfts.hContact) + ProtoBroadcastAck(MODULENAME, pfts.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, (HANDLE)id, 0); + + OpenCurrentFile(); + CheckCurrentFile(); + + return true; + } + + void SetStatus(int status, LPARAM param = 0) + { + if (pfts.hContact) + ProtoBroadcastAck(MODULENAME, pfts.hContact, ACKTYPE_FILE, status, (HANDLE)id, param); + } +}; + +#endif //_FILE_TRANSFER_H_
\ No newline at end of file |