summaryrefslogtreecommitdiff
path: root/protocols/Tox/src
diff options
context:
space:
mode:
authorAlexander Lantsev <aunsane@gmail.com>2014-08-29 22:11:08 +0000
committerAlexander Lantsev <aunsane@gmail.com>2014-08-29 22:11:08 +0000
commitbeaf93e92827b7bcc77c9f6b2a0c7097d355151c (patch)
tree0cc6549ce3f4073a261cdd10e3eed761fc3c4648 /protocols/Tox/src
parentd8e0b2d36e1944ab747012ed7ba4612f0da48854 (diff)
Tox: added files receiving
git-svn-id: http://svn.miranda-ng.org/main/trunk@10339 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Tox/src')
-rw-r--r--protocols/Tox/src/common.h1
-rw-r--r--protocols/Tox/src/file_transfer.h86
-rw-r--r--protocols/Tox/src/tox_account.cpp2
-rw-r--r--protocols/Tox/src/tox_events.cpp73
-rw-r--r--protocols/Tox/src/tox_proto.cpp52
-rw-r--r--protocols/Tox/src/tox_proto.h48
-rw-r--r--protocols/Tox/src/tox_transfers.cpp31
7 files changed, 250 insertions, 43 deletions
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 <iomanip>
#include <vector>
#include <regex>
+#include <map>
#include <newpluginapi.h>
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<CFile> files;
+ ULONG number;
-public:
+ HANDLE hWait;
+ LIST<CFile> 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<CToxProto>(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<uint8_t> 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<uint8_t> 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<CToxProto>
{
@@ -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<CFile> fileSendQueue;
+ LIST<CFileTransfer> fileTransfers;
+ std::map<uint8_t, FileTransferParam*> 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<uint8_t> 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