From 09fa77d73829e76123ac7a9b73bc90def12e9d9c Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 1 Feb 2015 09:23:58 +0000 Subject: Tox: - refactoring - updated tox core git-svn-id: http://svn.miranda-ng.org/main/trunk@11970 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/Tox_12.vcxproj | 1 + protocols/Tox/Tox_12.vcxproj.filters | 3 + protocols/Tox/bin/x64/libtox.dll | Bin 3959506 -> 3959539 bytes protocols/Tox/bin/x86/libtox.dll | Bin 3301258 -> 3301804 bytes protocols/Tox/include/tox.h | 25 ++--- protocols/Tox/src/common.h | 3 +- protocols/Tox/src/tox_account.cpp | 19 ++-- protocols/Tox/src/tox_address.h | 150 +++++++++++++++++++++++++++++ protocols/Tox/src/tox_avatars.cpp | 4 +- protocols/Tox/src/tox_contacts.cpp | 122 +++++++++++------------- protocols/Tox/src/tox_messages.cpp | 20 ++-- protocols/Tox/src/tox_profile.cpp | 9 +- protocols/Tox/src/tox_proto.cpp | 47 ++++----- protocols/Tox/src/tox_proto.h | 20 ++-- protocols/Tox/src/tox_search.cpp | 42 +++------ protocols/Tox/src/tox_transfer.cpp | 178 ++++++++++++++++++++++------------- protocols/Tox/src/tox_transfer.h | 35 +++---- protocols/Tox/src/tox_utils.cpp | 37 -------- 18 files changed, 425 insertions(+), 290 deletions(-) create mode 100644 protocols/Tox/src/tox_address.h diff --git a/protocols/Tox/Tox_12.vcxproj b/protocols/Tox/Tox_12.vcxproj index c1e0ab8b2e..c29ce07566 100644 --- a/protocols/Tox/Tox_12.vcxproj +++ b/protocols/Tox/Tox_12.vcxproj @@ -199,6 +199,7 @@ + diff --git a/protocols/Tox/Tox_12.vcxproj.filters b/protocols/Tox/Tox_12.vcxproj.filters index fee1c08363..0a3ec927ab 100644 --- a/protocols/Tox/Tox_12.vcxproj.filters +++ b/protocols/Tox/Tox_12.vcxproj.filters @@ -36,6 +36,9 @@ Header Files + + Header Files + diff --git a/protocols/Tox/bin/x64/libtox.dll b/protocols/Tox/bin/x64/libtox.dll index 6c68460b7c..dfe99f697f 100644 Binary files a/protocols/Tox/bin/x64/libtox.dll and b/protocols/Tox/bin/x64/libtox.dll differ diff --git a/protocols/Tox/bin/x86/libtox.dll b/protocols/Tox/bin/x86/libtox.dll index 39f1a65585..dca28deeaa 100644 Binary files a/protocols/Tox/bin/x86/libtox.dll and b/protocols/Tox/bin/x86/libtox.dll differ diff --git a/protocols/Tox/include/tox.h b/protocols/Tox/include/tox.h index db1b10331c..ee678cc1f5 100644 --- a/protocols/Tox/include/tox.h +++ b/protocols/Tox/include/tox.h @@ -38,11 +38,14 @@ extern "C" { #define TOX_MAX_STATUSMESSAGE_LENGTH 1007 #define TOX_MAX_FRIENDREQUEST_LENGTH 1016 -#define TOX_CLIENT_ID_SIZE 32 +#define TOX_PUBLIC_KEY_SIZE 32 +/* TODO: remove */ +#define TOX_CLIENT_ID_SIZE TOX_PUBLIC_KEY_SIZE + #define TOX_AVATAR_MAX_DATA_LENGTH 16384 #define TOX_HASH_LENGTH /*crypto_hash_sha256_BYTES*/ 32 -#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) +#define TOX_FRIEND_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) #define TOX_ENABLE_IPV6_DEFAULT 1 @@ -97,7 +100,7 @@ typedef struct Tox Tox; */ /* return TOX_FRIEND_ADDRESS_SIZE byte address to give to others. - * format: [client_id (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] + * format: [public_key (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)] */ void tox_get_address(const Tox *tox, uint8_t *address); @@ -124,18 +127,18 @@ int32_t tox_add_friend(Tox *tox, const uint8_t *address, const uint8_t *data, ui * return the friend number if success. * return -1 if failure. */ -int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *client_id); +int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *public_key); /* return the friend number associated to that client id. return -1 if no such friend */ -int32_t tox_get_friend_number(const Tox *tox, const uint8_t *client_id); +int32_t tox_get_friend_number(const Tox *tox, const uint8_t *public_key); -/* Copies the public key associated to that friend id into client_id buffer. - * Make sure that client_id is of size CLIENT_ID_SIZE. +/* Copies the public key associated to that friend id into public_key buffer. + * Make sure that public_key is of size TOX_PUBLIC_KEY_SIZE. * return 0 if success. * return -1 if failure. */ -int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *client_id); +int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *public_key); /* Remove a friend. * @@ -500,13 +503,13 @@ int tox_del_groupchat(Tox *tox, int groupnumber); */ int tox_group_peername(const Tox *tox, int groupnumber, int peernumber, uint8_t *name); -/* Copy the public key of peernumber who is in groupnumber to pk. - * pk must be TOX_CLIENT_ID_SIZE long. +/* Copy the public key of peernumber who is in groupnumber to public_key. + * public_key must be TOX_PUBLIC_KEY_SIZE long. * * returns 0 on success * returns -1 on failure */ -int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *pk); +int tox_group_peer_pubkey(const Tox *tox, int groupnumber, int peernumber, uint8_t *public_key); /* invite friendnumber to groupnumber * return 0 on success diff --git a/protocols/Tox/src/common.h b/protocols/Tox/src/common.h index 1250b10fd7..93b22b718e 100644 --- a/protocols/Tox/src/common.h +++ b/protocols/Tox/src/common.h @@ -9,7 +9,7 @@ #include #include #include -#include +//#include #include #include @@ -37,6 +37,7 @@ #include "version.h" #include "resource.h" +#include "tox_address.h" #include "tox_transfer.h" #include "tox_proto.h" diff --git a/protocols/Tox/src/tox_account.cpp b/protocols/Tox/src/tox_account.cpp index 3b4f61b32b..2aa3081442 100644 --- a/protocols/Tox/src/tox_account.cpp +++ b/protocols/Tox/src/tox_account.cpp @@ -84,15 +84,14 @@ bool CToxProto::InitToxCore() tox_callback_avatar_info(tox, OnGotFriendAvatarInfo, this); tox_callback_avatar_data(tox, OnGotFriendAvatarData, this); - std::vector pubKey(TOX_FRIEND_ADDRESS_SIZE); - tox_get_address(tox, &pubKey[0]); - std::string address = DataToHexString(pubKey); - setString(NULL, TOX_SETTINGS_ID, address.c_str()); + uint8_t data[TOX_FRIEND_ADDRESS_SIZE]; + tox_get_address(tox, data); + ToxHexAddress address(data, TOX_FRIEND_ADDRESS_SIZE); + setString(NULL, TOX_SETTINGS_ID, address); int size = tox_get_self_name_size(tox); - std::vector username(size); - tox_get_self_name(tox, &username[0]); - std::string nick(username.begin(), username.end()); + std::string nick(size, 0); + tox_get_self_name(tox, (uint8_t*)nick.data()); setWString("Nick", ptrW(Utf8DecodeW(nick.c_str()))); std::tstring avatarPath = GetAvatarFilePath(); @@ -117,7 +116,7 @@ bool CToxProto::InitToxCore() void CToxProto::UninitToxCore() { ptrA nickname(mir_utf8encodeW(ptrT(getTStringA("Nick")))); - tox_set_name(tox, (uint8_t*)(char*)nickname, (uint16_t)strlen(nickname)); + tox_set_name(tox, (uint8_t*)(char*)nickname, mir_strlen(nickname)); SaveToxProfile(); if (password != NULL) @@ -143,8 +142,6 @@ void CToxProto::DoBootstrap() void CToxProto::DoTox() { tox_do(tox); - - //PulseEvent(hToxEvent); uint32_t interval = tox_do_interval(tox); Sleep(interval); } @@ -178,7 +175,7 @@ void CToxProto::PollingThread(void*) isConnected = true; debugLogA("CToxProto::PollingThread: successfuly connected to DHT"); - LoadFriendList(); + ForkThread(&CToxProto::LoadFriendList, NULL); debugLogA("CToxProto::PollingThread: changing status from %i to %i", ID_STATUS_CONNECTING, m_iDesiredStatus); m_iStatus = m_iDesiredStatus; diff --git a/protocols/Tox/src/tox_address.h b/protocols/Tox/src/tox_address.h new file mode 100644 index 0000000000..b8ceccefae --- /dev/null +++ b/protocols/Tox/src/tox_address.h @@ -0,0 +1,150 @@ +#ifndef _TOX_ADDRESS_H_ +#define _TOX_ADDRESS_H_ + +class ToxHexAddress; +class ToxBinAddress; + +class ToxHexAddress +{ +private: + std::string hexData; +public: + ToxHexAddress(const char *hex) : hexData(hex) { } + ToxHexAddress(const std::string &hex) : hexData(hex) { } + ToxHexAddress(const ToxHexAddress &address) : hexData(address.hexData) { } + ToxHexAddress(const std::vector &bin) + { + this->ToxHexAddress::ToxHexAddress(bin.data(), bin.size()); + } + ToxHexAddress(const uint8_t *bin, int size = TOX_FRIEND_ADDRESS_SIZE) + { + char *hex = (char*)mir_alloc(size * 2 + 1); + hexData = bin2hex(bin, size, hex); + std::transform(hexData.begin(), hexData.end(), hexData.begin(), ::toupper); + mir_free(hex); + } + const size_t GetLength() const + { + return hexData.length(); + } + const ToxHexAddress GetPubKey() const + { + ToxHexAddress pubKey = hexData.substr(0, TOX_PUBLIC_KEY_SIZE * 2).c_str(); + return pubKey; + } + operator const char*() const + { + return hexData.c_str(); + } + ToxBinAddress ToBin() const; +}; + +class ToxBinAddress +{ +private: + std::vector binData; +public: + ToxBinAddress(const ToxBinAddress &address) : binData(address.binData) { } + ToxBinAddress(const std::vector &bin) : binData(bin) { } + ToxBinAddress(const uint8_t *bin, int size = TOX_FRIEND_ADDRESS_SIZE) : binData(bin, bin + size) { } + ToxBinAddress(const std::string &hex) + { + this->ToxBinAddress::ToxBinAddress(hex.c_str()); + } + ToxBinAddress(const char *hex) + { + char *endptr; + const char *pos = hex; + int size = mir_strlen(hex) / 2; + uint8_t *result = (uint8_t*)mir_alloc(size); + for (int i = 0; i < size; i++) + { + char buf[5] = { '0', 'x', pos[0], pos[1], 0 }; + binData.push_back((uint8_t)strtol(buf, &endptr, 0)); + pos += 2; + } + } + const ToxBinAddress GetPubKey() const + { + ToxBinAddress pubKey(binData.data(), TOX_PUBLIC_KEY_SIZE); + return pubKey; + } + operator const uint8_t*() const + { + return binData.data(); + } + ToxHexAddress ToHex() const + { + ToxHexAddress hex(binData.data(), binData.size()); + return hex; + } +}; + +ToxBinAddress ToxHexAddress::ToBin() const +{ + ToxBinAddress bin(hexData.c_str()); + return bin; +} + +/*class ToxAddress +{ +private: + std::string hexData; + + class ToxBytes + { + private: + uint8_t *bytes; + + public: + ToxBytes(uint8_t *bytes) : bytes(bytes) { } + ~ToxBytes() { if (bytes) mir_free(bytes); } + + operator const uint8_t*() { return bytes; } + }; + +public: + ToxAddress(const char *hex) : hexData(hex) { } + ToxAddress(const std::string &hex) : hexData(hex) { } + ToxAddress(const ToxAddress &address) : hexData(address.hexData) { } + ToxAddress(const uint8_t *bin, int size = TOX_FRIEND_ADDRESS_SIZE) + //: binData(bin, bin + size) + { + char *hex = (char*)mir_alloc(size * 2 + 1); + std::string hexData = bin2hex(bin, size, hex); + std::transform(hexData.begin(), hexData.end(), hexData.begin(), ::toupper); + //mir_free(hex); + } + + ~ToxAddress() + { + int i = 0; + } + + operator const char*() const + { + return hexData.c_str(); + } + + ToxBytes AsBytes() const + { + char *endptr; + const char *pos = hexData.c_str(); + int size = hexData.length() / 2; + uint8_t *result = (uint8_t*)mir_alloc(size); + for (int i = 0; i < size; i++) + { + char buf[5] = { '0', 'x', pos[0], pos[1], 0 }; + result[i] = (uint8_t)strtol(buf, &endptr, 0); + pos += 2; + } + return ToxBytes(result); + } + + std::string AsPubKey() const + { + return hexData.substr(0, TOX_PUBLIC_KEY_SIZE * 2).c_str(); + } +};*/ + +#endif //_TOX_ADDRESS_H_ \ No newline at end of file diff --git a/protocols/Tox/src/tox_avatars.cpp b/protocols/Tox/src/tox_avatars.cpp index b69c462559..8f4410c5f3 100644 --- a/protocols/Tox/src/tox_avatars.cpp +++ b/protocols/Tox/src/tox_avatars.cpp @@ -196,7 +196,7 @@ void CToxProto::OnGotFriendAvatarInfo(Tox *tox, int32_t number, uint8_t format, { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { std::tstring path = proto->GetAvatarFilePath(hContact); @@ -232,7 +232,7 @@ void CToxProto::OnGotFriendAvatarData(Tox *tox, int32_t number, uint8_t format, { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { db_set_blob(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, hash, TOX_HASH_LENGTH); diff --git a/protocols/Tox/src/tox_contacts.cpp b/protocols/Tox/src/tox_contacts.cpp index 30c9fcc486..0808837727 100644 --- a/protocols/Tox/src/tox_contacts.cpp +++ b/protocols/Tox/src/tox_contacts.cpp @@ -41,14 +41,15 @@ MCONTACT CToxProto::GetContactFromAuthEvent(MEVENT hEvent) return DbGetAuthEventContact(&dbei); } -bool CToxProto::IsMe(const std::string &id) +MCONTACT CToxProto::GetContact(const int friendNumber) { - std::string ownId = getStringA(NULL, TOX_SETTINGS_ID); - - return strnicmp(id.c_str(), ownId.c_str(), TOX_CLIENT_ID_SIZE) == 0; + uint8_t data[TOX_PUBLIC_KEY_SIZE]; + tox_get_client_id(tox, friendNumber, data); + ToxHexAddress pubKey(data, TOX_PUBLIC_KEY_SIZE); + return GetContact(pubKey); } -MCONTACT CToxProto::FindContact(const std::string &id) +MCONTACT CToxProto::GetContact(const char *pubKey) { MCONTACT hContact = NULL; for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) @@ -56,24 +57,14 @@ MCONTACT CToxProto::FindContact(const std::string &id) DBVARIANT dbv; if (!db_get(hContact, m_szModuleName, TOX_SETTINGS_ID, &dbv)) { - std::string clientId; - - // temporary code for contact id conversion - if (dbv.type == DBVT_BLOB) + std::string contactPubKey; + if (dbv.type == DBVT_ASCIIZ) { - std::vector pubKey(dbv.cpbVal); - memcpy(&pubKey[0], dbv.pbVal, dbv.cpbVal); - clientId = DataToHexString(pubKey); - delSetting(hContact, TOX_SETTINGS_ID); - setString(hContact, TOX_SETTINGS_ID, clientId.c_str()); - } - else if (dbv.type == DBVT_ASCIIZ) - { - clientId = dbv.pszVal; + contactPubKey = dbv.pszVal; } db_free(&dbv); - - if (mir_strcmpi(id.c_str(), clientId.c_str()) == 0) + // check only public key part of address + if (strnicmp(pubKey, contactPubKey.c_str(), TOX_PUBLIC_KEY_SIZE) == 0) { break; } @@ -82,25 +73,16 @@ MCONTACT CToxProto::FindContact(const std::string &id) return hContact; } -MCONTACT CToxProto::FindContact(const int friendNumber) +MCONTACT CToxProto::AddContact(const char *address, const std::tstring &dnsId, bool isTemporary) { - std::vector clientId(TOX_CLIENT_ID_SIZE); - tox_get_client_id(tox, friendNumber, clientId.data()); - - std::string id = DataToHexString(clientId); - - return FindContact(id); -} - -MCONTACT CToxProto::AddContact(const std::string &id, const std::tstring &dnsId, bool isTemporary) -{ - MCONTACT hContact = FindContact(id); + MCONTACT hContact = GetContact(address); if (!hContact) { hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0); CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)m_szModuleName); - setString(hContact, TOX_SETTINGS_ID, id.c_str()); + setString(hContact, TOX_SETTINGS_ID, address); + if (!dnsId.empty()) { setTString(hContact, TOX_SETTINGS_DNS, dnsId.c_str()); @@ -124,7 +106,7 @@ MCONTACT CToxProto::AddContact(const std::string &id, const std::tstring &dnsId, return hContact; } -void CToxProto::LoadFriendList() +void CToxProto::LoadFriendList(void*) { uint32_t count = tox_count_friendlist(tox); if (count > 0) @@ -132,21 +114,24 @@ void CToxProto::LoadFriendList() int32_t *friends = (int32_t*)mir_alloc(count * sizeof(int32_t)); tox_get_friendlist(tox, friends, count); - std::vector id(TOX_CLIENT_ID_SIZE); + uint8_t data[TOX_PUBLIC_KEY_SIZE]; for (uint32_t i = 0; i < count; ++i) { - tox_get_client_id(tox, friends[i], id.data()); - MCONTACT hContact = AddContact(DataToHexString(id), _T("")); + tox_get_client_id(tox, friends[i], data); + ToxHexAddress pubKey(data, TOX_PUBLIC_KEY_SIZE); + MCONTACT hContact = AddContact(pubKey, _T("")); if (hContact) { delSetting(hContact, "Auth"); delSetting(hContact, "Grant"); int size = tox_get_name_size(tox, friends[i]); - std::vector username(size); - tox_get_name(tox, friends[i], &username[0]); - std::string nick(username.begin(), username.end()); - setWString(hContact, "Nick", ptrW(Utf8DecodeW(nick.c_str()))); + if (size != TOX_ERROR) + { + std::string nick(size, 0); + tox_get_name(tox, friends[i], (uint8_t*)nick.data()); + setWString(hContact, "Nick", ptrW(Utf8DecodeW(nick.c_str()))); + } uint64_t timestamp = tox_get_last_online(tox, friends[i]); if (timestamp) @@ -171,10 +156,8 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM lParam) return 1; } - std::string id = getStringA(hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - - uint32_t number = tox_get_friend_number(tox, clientId.data()); + ToxBinAddress pubKey = ptrA(getStringA(hContact, TOX_SETTINGS_ID)); + int32_t number = tox_get_friend_number(tox, pubKey); if (number == TOX_ERROR || tox_del_friend(tox, number) == TOX_ERROR) { return 1; @@ -183,15 +166,12 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM lParam) return 0; } -void CToxProto::OnFriendRequest(Tox *tox, const uint8_t *address, const uint8_t *message, const uint16_t messageSize, void *arg) +void CToxProto::OnFriendRequest(Tox *tox, const uint8_t *data, const uint8_t *message, const uint16_t messageSize, void *arg) { CToxProto *proto = (CToxProto*)arg; - // trim tox address to tox id - std::vector clientId(address, address + TOX_CLIENT_ID_SIZE); - std::string id = proto->DataToHexString(clientId); - - MCONTACT hContact = proto->AddContact(id, _T("")); + ToxHexAddress address(data, TOX_FRIEND_ADDRESS_SIZE); + MCONTACT hContact = proto->AddContact(address, _T("")); if (!hContact) { return; @@ -202,7 +182,7 @@ void CToxProto::OnFriendRequest(Tox *tox, const uint8_t *address, const uint8_t PROTORECVEVENT pre = { 0 }; pre.flags = PREF_UTF; pre.timestamp = time(NULL); - pre.lParam = (DWORD)(sizeof(DWORD)* 2 + id.length() + messageSize + 5); + pre.lParam = (DWORD)(sizeof(DWORD) * 2 + address.GetLength() + messageSize + 5); /*blob is: 0(DWORD), hContact(DWORD), nick(ASCIIZ), firstName(ASCIIZ), lastName(ASCIIZ), id(ASCIIZ), reason(ASCIIZ)*/ PBYTE pBlob, pCurBlob; @@ -213,9 +193,9 @@ void CToxProto::OnFriendRequest(Tox *tox, const uint8_t *address, const uint8_t *((PDWORD)pCurBlob) = (DWORD)hContact; pCurBlob += sizeof(DWORD); pCurBlob += 3; - strcpy((char *)pCurBlob, id.c_str()); - pCurBlob += id.length() + 1; - strcpy((char *)pCurBlob, (char*)message); + mir_strcpy((char *)pCurBlob, address); + pCurBlob += address.GetLength() + 1; + mir_strcpy((char *)pCurBlob, (char*)message); pre.szMessage = (char*)pBlob; ProtoChainRecv(hContact, PSR_AUTH, 0, (LPARAM)&pre); @@ -225,7 +205,7 @@ void CToxProto::OnFriendNameChange(Tox *tox, const int friendNumber, const uint8 { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { proto->setString(hContact, "Nick", (char*)name); @@ -236,7 +216,7 @@ void CToxProto::OnStatusMessageChanged(Tox *tox, const int friendNumber, const u { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { ptrW statusMessage(mir_utf8decodeW((char*)message)); @@ -248,7 +228,7 @@ void CToxProto::OnUserStatusChanged(Tox *tox, int32_t friendNumber, uint8_t user { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { TOX_USERSTATUS userstatus = (TOX_USERSTATUS)usertatus; @@ -261,9 +241,7 @@ void CToxProto::OnConnectionStatusChanged(Tox *tox, const int friendNumber, cons { CToxProto *proto = (CToxProto*)arg; - //mir_cslock lock(proto->toxLock); - - MCONTACT hContact = proto->FindContact(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { int newStatus = status ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; @@ -273,24 +251,34 @@ void CToxProto::OnConnectionStatusChanged(Tox *tox, const int friendNumber, cons tox_send_avatar_info(proto->tox, friendNumber); proto->delSetting(hContact, "Auth"); - for (int i = 0; i < proto->transfers->Count(); i++) + for (size_t i = 0; i < proto->transfers->Count(); i++) { // only for receiving - FileTransferParam *transfer = proto->transfers->At(i); + FileTransferParam *transfer = proto->transfers->GetAt(i); if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 1) { - transfer->Resume(tox); + if (transfer->Resume(tox) == TOX_ERROR) + { + transfer->Cancel(tox); + proto->debugLogA("CToxProto::OnConnectionStatusChanged: failed to resuming of file (%d)", + transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); + continue; + } + proto->debugLogA("CToxProto::OnConnectionStatusChanged: ask to resume the receiving at %llu of %llu of file (%d)", + transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); } } } else { - for (int i = 0; i < proto->transfers->Count(); i++) + for (size_t i = 0; i < proto->transfers->Count(); i++) { - FileTransferParam *transfer = proto->transfers->At(i); + FileTransferParam *transfer = proto->transfers->GetAt(i); if (transfer->friendNumber == friendNumber) { - transfer->status = PAUSED; + mir_cslock(transfer->fileLock); + + transfer->status = BROKEN; } } } diff --git a/protocols/Tox/src/tox_messages.cpp b/protocols/Tox/src/tox_messages.cpp index 51f255b546..a050b7f962 100644 --- a/protocols/Tox/src/tox_messages.cpp +++ b/protocols/Tox/src/tox_messages.cpp @@ -4,7 +4,7 @@ void CToxProto::OnFriendMessage(Tox *tox, const int number, const uint8_t *messa { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { PROTORECVEVENT recv = { 0 }; @@ -20,7 +20,7 @@ void CToxProto::OnFriendAction(Tox *tox, const int number, const uint8_t *action { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { proto->AddDbEvent( @@ -35,9 +35,7 @@ void CToxProto::OnFriendAction(Tox *tox, const int number, const uint8_t *action int __cdecl CToxProto::SendMsg(MCONTACT hContact, int flags, const char* msg) { - 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 = 0;// getDword(hContact, TOX_SETTINGS_NUMBER, TOX_ERROR); if (number == TOX_ERROR) { debugLogA("CToxProto::SendMsg: failed to get friend number"); @@ -48,11 +46,11 @@ int __cdecl CToxProto::SendMsg(MCONTACT hContact, int flags, const char* msg) { if (strncmp(msg, "/me ", 4) != 0) { - result = tox_send_message(tox, number, (uint8_t*)msg, (uint16_t)strlen(msg)); + result = tox_send_message(tox, number, (uint8_t*)msg, mir_strlen(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], mir_strlen(msg) - 4); } } @@ -68,7 +66,7 @@ void CToxProto::OnReadReceipt(Tox *tox, int32_t number, uint32_t receipt, void * { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { proto->ProtoBroadcastAck( @@ -106,7 +104,7 @@ void CToxProto::OnTypingChanged(Tox *tox, const int number, uint8_t isTyping, vo { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(number); + MCONTACT hContact = proto->GetContact(number); if (hContact) { CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)isTyping); @@ -117,9 +115,7 @@ int __cdecl CToxProto::UserIsTyping(MCONTACT hContact, int type) { if (hContact && IsOnline()) { - 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 = 0;//getDword(hContact, TOX_SETTINGS_NUMBER, TOX_ERROR); if (number >= 0) { tox_set_user_is_typing(tox, number, type); diff --git a/protocols/Tox/src/tox_profile.cpp b/protocols/Tox/src/tox_profile.cpp index 898899bff1..d169b21f78 100644 --- a/protocols/Tox/src/tox_profile.cpp +++ b/protocols/Tox/src/tox_profile.cpp @@ -31,8 +31,8 @@ bool CToxProto::LoadToxProfile() } fseek(profile, 0, SEEK_END); - size_t size = ftell(profile); - fseek(profile, 0, SEEK_SET); + size_t size = _ftelli64(profile); + rewind(profile); if (size == 0) { fclose(profile); @@ -41,8 +41,7 @@ bool CToxProto::LoadToxProfile() } uint8_t *data = (uint8_t*)mir_calloc(size); - size_t read = fread((char*)data, sizeof(char), size, profile); - if (size != read) + if (fread((char*)data, sizeof(char), size, profile) != size) { fclose(profile); debugLogA("CToxProto::LoadToxData: could not read tox profile"); @@ -66,7 +65,7 @@ bool CToxProto::LoadToxProfile() } } - if (tox_encrypted_load(tox, data, size, (uint8_t*)password, strlen(password)) == TOX_ERROR) + if (tox_encrypted_load(tox, data, size, (uint8_t*)password, mir_strlen(password)) == TOX_ERROR) { debugLogA("CToxProto::LoadToxData: could not decrypt tox profile"); mir_free(data); diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp index 36dba649ea..bf122b72e7 100644 --- a/protocols/Tox/src/tox_proto.cpp +++ b/protocols/Tox/src/tox_proto.cpp @@ -48,8 +48,6 @@ CToxProto::CToxProto(const char* protoName, const TCHAR* userName) : // transfers transfers = new CTransferList(); - - hToxEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } CToxProto::~CToxProto() @@ -83,22 +81,26 @@ DWORD_PTR __cdecl CToxProto::GetCaps(int type, MCONTACT hContact) return 0; } -MCONTACT __cdecl CToxProto::AddToList(int flags, PROTOSEARCHRESULT* psr) +MCONTACT __cdecl CToxProto::AddToList(int flags, PROTOSEARCHRESULT *psr) { - std::string address(mir_t2a(psr->id)); - if (IsMe(address)) + std::string address(ptrA(mir_t2a(psr->id))); + ptrA myAddress(getStringA(NULL, TOX_SETTINGS_ID)); + if (strnicmp(address.c_str(), myAddress, TOX_PUBLIC_KEY_SIZE) == 0) + { + ShowNotification(TranslateT("You cannot add yourself to your contact list"), 0); + return NULL; + } + MCONTACT hContact = GetContact(address.c_str()); + if (hContact) { - debugLogA("CToxProto::AddToList: you cannot add yourself to friend list"); + ShowNotification(TranslateT("Contact already in your contact list"), 0, hContact); return NULL; } - // set tox address as contact id - return AddContact(address, _T(""), flags & PALF_TEMPORARY); + // set tox address as contact public key + return AddContact(address.c_str(), _T(""), flags & PALF_TEMPORARY); } -MCONTACT __cdecl CToxProto::AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) -{ - return 0; -} +MCONTACT __cdecl CToxProto::AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) { return 0; } int __cdecl CToxProto::Authorize(MEVENT hDbEvent) { @@ -108,13 +110,16 @@ int __cdecl CToxProto::Authorize(MEVENT hDbEvent) return 1; } - std::string id = getStringA(hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - if (tox_add_friend_norequest(tox, clientId.data()) != TOX_ERROR) + ToxBinAddress address = ptrA(getStringA(hContact, TOX_SETTINGS_ID)); + ToxBinAddress pubKey = address.GetPubKey(); + if (tox_add_friend_norequest(tox, pubKey) == TOX_ERROR) { return 1; } + // trim address to public key + setString(hContact, TOX_SETTINGS_ID, pubKey.ToHex()); + db_unset(hContact, "CList", "NotOnList"); delSetting(hContact, "Grant"); @@ -132,14 +137,12 @@ int __cdecl CToxProto::AuthRequest(MCONTACT hContact, const PROTOCHAR *szMessage { ptrA reason(mir_utf8encodeW(szMessage)); - std::string address = getStringA(hContact, TOX_SETTINGS_ID); - std::vector pubKey = HexStringToData(address); - int32_t number = tox_add_friend(tox, pubKey.data(), (uint8_t*)(char*)reason, (uint16_t)strlen(reason)); + ToxBinAddress address = ptrA(getStringA(hContact, TOX_SETTINGS_ID)); + int32_t number = tox_add_friend(tox, address, (uint8_t*)(char*)reason, mir_strlen(reason)); if (number > TOX_ERROR) { - // change tox address in contact id by tox id - std::string id = ToxAddressToId(address); - setString(hContact, TOX_SETTINGS_ID, id.c_str()); + // trim address to public key + setString(hContact, TOX_SETTINGS_ID, address.ToHex().GetPubKey()); db_unset(hContact, "CList", "NotOnList"); delSetting(hContact, "Grant"); @@ -260,7 +263,7 @@ int __cdecl CToxProto::SetAwayMsg(int iStatus, const PROTOCHAR *msg) //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) + if (tox_set_status_message(tox, (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUSMESSAGE_LENGTH, mir_strlen(statusMessage))) == TOX_ERROR) { debugLogA("CToxProto::SetAwayMsg: failed to set status status message %s", msg); } diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h index eab3eb509b..03fdfa1a78 100644 --- a/protocols/Tox/src/tox_proto.h +++ b/protocols/Tox/src/tox_proto.h @@ -68,7 +68,7 @@ private: char *password; mir_cs toxLock; TCHAR *accountName; - HANDLE hNetlib, hPollingThread, hToxEvent; + HANDLE hNetlib, hPollingThread; bool isTerminated, isConnected; CTransferList *transfers; @@ -119,18 +119,19 @@ private: WORD GetContactStatus(MCONTACT hContact); void SetContactStatus(MCONTACT hContact, WORD status); void SetAllContactsStatus(WORD status); - bool IsMe(const std::string &id); - MCONTACT FindContact(const std::string &id); - MCONTACT FindContact(const int friendNumber); - MCONTACT AddContact(const std::string &id, const std::tstring &dnsId, bool isTemporary = false); + + MCONTACT GetContact(const int friendNumber); + MCONTACT GetContact(const char *pubKey); + + MCONTACT AddContact(const char *address, const std::tstring &dnsId, bool isTemporary = false); MCONTACT GetContactFromAuthEvent(MEVENT hEvent); - void LoadFriendList(); + void __cdecl LoadFriendList(void*); 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 OnFriendRequest(Tox *tox, const uint8_t *pubKey, const uint8_t *message, const uint16_t messageSize, 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); @@ -178,11 +179,6 @@ private: static void ShowNotification(const TCHAR *caption, const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); MEVENT AddDbEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob); - - std::vector HexStringToData(std::string hex); - std::string DataToHexString(std::vector); - - std::string ToxAddressToId(std::string); static bool IsFileExists(std::tstring path); }; diff --git a/protocols/Tox/src/tox_search.cpp b/protocols/Tox/src/tox_search.cpp index 8e1df68786..d62eccd593 100644 --- a/protocols/Tox/src/tox_search.cpp +++ b/protocols/Tox/src/tox_search.cpp @@ -23,7 +23,7 @@ void CToxProto::SearchByNameAsync(void *arg) uint8_t dnsString[256]; uint32_t requestId = 0; - int length = tox_generate_dns3_string(dns, dnsString, sizeof(dnsString), &requestId, (uint8_t*)name, strlen(name)); + int length = tox_generate_dns3_string(dns, dnsString, sizeof(dnsString), &requestId, (uint8_t*)name, mir_strlen(name)); if (length != TOX_ERROR) { dnsString[length] = 0; @@ -40,14 +40,14 @@ void CToxProto::SearchByNameAsync(void *arg) if (record->wType == DNS_TYPE_TEXT && txt->dwStringCount) { char *recordId = &txt->pStringArray[0][10]; - std::vector address(TOX_FRIEND_ADDRESS_SIZE); - if (tox_decrypt_dns3_TXT(dns, &address[0], (uint8_t*)recordId, strlen(recordId), requestId) != TOX_ERROR) + uint8_t data[TOX_FRIEND_ADDRESS_SIZE]; + if (tox_decrypt_dns3_TXT(dns, data, (uint8_t*)recordId, mir_strlen(recordId), requestId) != TOX_ERROR) { - std::string id = DataToHexString(address); + ToxHexAddress address(data, TOX_FRIEND_ADDRESS_SIZE); PROTOSEARCHRESULT psr = { sizeof(PROTOSEARCHRESULT) }; psr.flags = PSR_TCHAR; - psr.id = mir_a2t(id.c_str()); + psr.id = mir_a2t(address); psr.nick = mir_utf8decodeT(name); TCHAR email[MAX_PATH]; @@ -115,30 +115,18 @@ HWND __cdecl CToxProto::SearchAdvanced(HWND owner) if (std::regex_search(query, match, regex)) { std::string address = match[1]; - if (IsMe(address)) - { - ShowNotification(TranslateT("You cannot add yourself to friend list"), 0); - } - else - { - MCONTACT hContact = FindContact(address); - if (!hContact) - { - PROTOSEARCHRESULT psr = { sizeof(psr) }; - psr.flags = PSR_TCHAR; - psr.id = mir_a2t(query.c_str()); + MCONTACT hContact = GetContact(address.c_str()); - ADDCONTACTSTRUCT acs = { HANDLE_SEARCHRESULT }; - acs.szProto = m_szModuleName; - acs.psr = &psr; + PROTOSEARCHRESULT psr = { sizeof(psr) }; + psr.flags = PSR_TCHAR; + psr.id = mir_a2t(query.c_str()); + + ADDCONTACTSTRUCT acs = { HANDLE_SEARCHRESULT }; + acs.szProto = m_szModuleName; + acs.psr = &psr; + + CallService(MS_ADDCONTACT_SHOW, (WPARAM)owner, (LPARAM)&acs); - CallService(MS_ADDCONTACT_SHOW, (WPARAM)owner, (LPARAM)&acs); - } - else - { - ShowNotification(TranslateT("Contact already in your contact list"), 0, hContact); - } - } ForkThread(&CToxProto::SearchFailedAsync, NULL); } else diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp index ce8488438b..a56799f971 100644 --- a/protocols/Tox/src/tox_transfer.cpp +++ b/protocols/Tox/src/tox_transfer.cpp @@ -3,12 +3,11 @@ /* FILE RECEIVING */ // incoming file flow -// send it through miranda 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(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { TCHAR *name = mir_utf8decodeT((char*)fileName); @@ -45,7 +44,7 @@ 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->RenameName(fullPath); + transfer->Rename(fullPath); if (!ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, (HANDLE)transfer, (LPARAM)&transfer->pfts)) { @@ -73,7 +72,7 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR switch (*action) { case FILERESUME_RENAME: - transfer->RenameName(*szFilename); + transfer->Rename(*szFilename); result = transfer->OpenFile(_T("wb")); break; @@ -83,7 +82,7 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR case FILERESUME_SKIP: result = false; - return 0; + break; case FILERESUME_RESUME: result = transfer->OpenFile(_T("ab")); @@ -93,6 +92,7 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR if (result) { transfer->Start(tox); + debugLogA("CToxProto::FileResume: start receiving file (%d)", transfer->fileNumber); } else { @@ -109,37 +109,40 @@ void CToxProto::OnFileData(Tox *tox, int32_t friendNumber, uint8_t fileNumber, c { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->FindContact(friendNumber); - if (hContact) + MCONTACT hContact = proto->GetContact(friendNumber); + if (hContact == NULL) { - FileTransferParam *transfer = proto->transfers->Get(fileNumber); - if (transfer == NULL) - { - tox_file_send_control(tox, friendNumber, 1, fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - return; - } + proto->debugLogA("CToxProto::OnFileData: cannot find contact by number (%d)", friendNumber); + tox_file_send_control(tox, friendNumber, 1, fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + return; + } - if (fwrite(data, sizeof(uint8_t), size, transfer->hFile) != size) - { - 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); - } + FileTransferParam *transfer = proto->transfers->Get(fileNumber); + if (transfer == NULL) + { + proto->debugLogA("CToxProto::OnFileData: cannot find transfer by number (%d)", fileNumber); + transfer->Fail(tox); + return; + } - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); + if (fwrite(data, sizeof(uint8_t), size, transfer->hFile) != size) + { + 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); + return; } + + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); } /* FILE SENDING */ // 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*, PROTOCHAR **ppszFiles) { - std::string id = getStringA(hContact, TOX_SETTINGS_ID); - std::vector clientId = HexStringToData(id); - uint32_t friendNumber = tox_get_friend_number(tox, clientId.data()); + uint32_t friendNumber = 0;// getDword(hContact, TOX_SETTINGS_NUMBER, TOX_ERROR); TCHAR *fileName = _tcsrchr(ppszFiles[0], '\\') + 1; @@ -148,19 +151,19 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR *szDescrip _tcsncpy(fileDir, ppszFiles[0], fileDirLength); fileDir[fileDirLength] = '\0'; - size_t fileSize = 0; FILE *hFile = _tfopen(ppszFiles[0], _T("rb")); if (hFile == NULL) { debugLogA("CToxProto::SendFilesAsync: cannot open file"); return NULL; } + fseek(hFile, 0, SEEK_END); - fileSize = ftell(hFile); - fseek(hFile, 0, SEEK_SET); + size_t fileSize = _ftelli64(hFile); + rewind(hFile); char *name = mir_utf8encodeW(fileName); - int fileNumber = tox_new_file_sender(tox, friendNumber, fileSize, (uint8_t*)name, strlen(name)); + int fileNumber = tox_new_file_sender(tox, friendNumber, fileSize, (uint8_t*)name, mir_strlen(name)); if (fileNumber < 0) { debugLogA("CToxProto::SendFilesAsync: cannot send file"); @@ -186,51 +189,62 @@ void CToxProto::SendFileAsync(void *arg) debugLogA("CToxProto::SendFileAsync: start sending file (%d)", transfer->fileNumber); ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)transfer, 0); + size_t dataSize = 0, fileProgress = 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); - - uint16_t chunkSize = min(fileSize, (size_t)tox_file_data_size(tox, transfer->friendNumber)); + size_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) + + while (transfer->status < FAILED && transfer->hFile != NULL && fileProgress < fileSize) { - if (transfer->status == PAUSED) + mir_cslockfull locker(transfer->fileLock); + + if (transfer->status == PAUSED || transfer->status == BROKEN) { - Sleep(1000); + if (transfer->status == BROKEN) + { + dataSize = 0; + } + locker.unlock(); + Sleep(100); continue; } - //mir_cslock lock(toxLock); - - uint16_t size = min(chunkSize, fileSize - fileProgress); - if (fread(data, sizeof(uint8_t), size, transfer->hFile) != size) + if (dataSize == 0) { - 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; + dataSize = min(chunkSize, fileSize - fileProgress); + if (fread(data, sizeof(uint8_t), dataSize, transfer->hFile) != dataSize) + { + debugLogA("CToxProto::SendFileAsync: failed to read from file (%d)", transfer->fileNumber); + debugLogA("CToxProto::OnFileRequest: failure of sending at %llu of %llu of file (%d)", fileProgress, fileSize, transfer->fileNumber); + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + transfer->Fail(tox); + return; + } } - if (tox_file_send_data(tox, transfer->friendNumber, transfer->fileNumber, data, size) == TOX_ERROR) + if (tox_file_send_data(tox, transfer->friendNumber, transfer->fileNumber, data, dataSize) == TOX_ERROR) { - fseek(transfer->hFile, -size, SEEK_CUR); + //fseek(transfer->hFile, -(long)size, SEEK_CUR); + locker.unlock(); + //Sleep(100); continue; } - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += size; + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += dataSize; ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); + dataSize = 0; } + mir_free(data); - if (transfer->status == STARTED) + if (transfer->status != STARTED) { - //mir_cslock lock(toxLock); - transfer->Finish(tox); + transfer->Fail(tox); } + transfer->Finish(tox); } -/* GENERAL */ +/* COMMON */ // file request is cancelled int __cdecl CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) @@ -252,12 +266,9 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_se { CToxProto *proto = (CToxProto*)arg; - //mir_cslock lock(proto->toxLock); - - MCONTACT hContact = proto->FindContact(friendNumber); + MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { - FileTransferParam *transfer = proto->transfers->Get(fileNumber); if (transfer == NULL) { @@ -268,15 +279,17 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_se switch (type) { case TOX_FILECONTROL_ACCEPT: + // if friend allow file request if (receive_send == 1) { - // if friend allow file request if (transfer->status == NONE) { proto->ForkThread(&CToxProto::SendFileAsync, transfer); } else { + mir_cslock locker(transfer->fileLock); + // unpause file transfer transfer->status = STARTED; } @@ -284,24 +297,53 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_se break; case TOX_FILECONTROL_PAUSE: - transfer->status = PAUSED; + { + mir_cslock locker(transfer->fileLock); + + transfer->status = PAUSED; + } break; case TOX_FILECONTROL_RESUME_BROKEN: - // only for sending - if (receive_send == 0) + if (receive_send == 1) { + mir_cslock locker(transfer->fileLock); + + // if receiver ask to resume transfer uint64_t progress = *(uint64_t*)data; - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = progress; - fseek(transfer->hFile, progress, SEEK_SET); - transfer->Start(tox); + if (progress >= transfer->pfts.currentFileSize || length != sizeof(uint64_t)) + { + transfer->Fail(tox); + } + if (tox_file_send_control(tox, friendNumber, transfer->GetDirection(), fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0) == TOX_ERROR) + { + proto->debugLogA("CToxProto::OnFileRequest: failed to resume sending file (%d)", + transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + transfer->Fail(tox); + break; + } + if (transfer->pfts.currentFileProgress != progress) + { + proto->debugLogA("CToxProto::OnFileRequest: change file position from %llu to %llu of file (%d)", + transfer->pfts.currentFileProgress, progress, transfer->fileNumber); + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = progress; + _fseeki64(transfer->hFile, progress, SEEK_SET); + } + proto->debugLogA("CToxProto::OnFileRequest: resumption of sending at %llu of %llu of file (%d)", + transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); + transfer->status = STARTED; } break; case TOX_FILECONTROL_KILL: - transfer->status = CANCELED; - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); - proto->transfers->Remove(transfer); + { + mir_cslock locker(transfer->fileLock); + + transfer->status = CANCELED; + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); + proto->transfers->Remove(transfer); + } break; case TOX_FILECONTROL_FINISHED: @@ -314,6 +356,8 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_se { proto->debugLogA("CToxProto::OnFileRequest: finished sending file (%d)", fileNumber); } + proto->debugLogA("CToxProto::OnFileRequest: %llu of %llu of file(%d) was transferred successfully", + transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)transfer, 0); proto->transfers->Remove(transfer); break; diff --git a/protocols/Tox/src/tox_transfer.h b/protocols/Tox/src/tox_transfer.h index f0732ca3b0..7cbbffe3ee 100644 --- a/protocols/Tox/src/tox_transfer.h +++ b/protocols/Tox/src/tox_transfer.h @@ -6,6 +6,7 @@ enum FILE_TRANSFER_STATUS NONE, STARTED, PAUSED, + BROKEN, FAILED, CANCELED, FINISHED, @@ -17,6 +18,7 @@ struct FileTransferParam PROTOFILETRANSFERSTATUS pfts; FILE_TRANSFER_STATUS status; FILE *hFile; + mir_cs fileLock; int friendNumber; int fileNumber; @@ -45,37 +47,37 @@ struct FileTransferParam return hFile != NULL; } - void Start(Tox *tox) + int Start(Tox *tox) { status = STARTED; - tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0); + return tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0); } - void Resume(Tox *tox) + int Resume(Tox *tox) { status = STARTED; - tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_RESUME_BROKEN, (uint8_t*)&pfts.currentFileProgress, sizeof(uint64_t)); + return tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_RESUME_BROKEN, (uint8_t*)&pfts.currentFileProgress, sizeof(pfts.currentFileProgress)); } - void Fail(Tox *tox) + int Fail(Tox *tox) { status = FAILED; - tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + return tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); } - void Cancel(Tox *tox) + int Cancel(Tox *tox) { status = FINISHED; - tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + return tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_KILL, NULL, 0); } - void Finish(Tox *tox) + int Finish(Tox *tox) { status = FINISHED; - tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); + return tox_file_send_control(tox, friendNumber, GetDirection(), fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0); } - void RenameName(const TCHAR* fileName) + void Rename(const TCHAR* fileName) { pfts.ptszFiles[0] = replaceStrT(pfts.tszCurrentFile, fileName); } @@ -94,9 +96,10 @@ struct FileTransferParam } mir_free(pfts.pszFiles[0]); mir_free(pfts.pszFiles); - if (hFile) + if (hFile != NULL) { fclose(hFile); + hFile = NULL; } } }; @@ -107,7 +110,7 @@ private: std::map transfers; public: - int Count() const + size_t Count() const { return transfers.size(); } @@ -120,7 +123,7 @@ public: } } - FileTransferParam * Get(uint8_t fileNumber) + FileTransferParam* Get(uint8_t fileNumber) { if (transfers.find(fileNumber) != transfers.end()) { @@ -129,9 +132,9 @@ public: return NULL; } - FileTransferParam * At(int index) + FileTransferParam* GetAt(size_t index) { - if (Count() < index) + if (index < Count()) { std::map::iterator it = transfers.begin(); std::advance(it, index); diff --git a/protocols/Tox/src/tox_utils.cpp b/protocols/Tox/src/tox_utils.cpp index e3bf7d9707..14caa84026 100644 --- a/protocols/Tox/src/tox_utils.cpp +++ b/protocols/Tox/src/tox_utils.cpp @@ -73,43 +73,6 @@ MEVENT CToxProto::AddDbEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWOR return db_event_add(hContact, &dbei); } -std::vector CToxProto::HexStringToData(std::string hex) -{ - std::stringstream ss; - std::vector data; - - size_t count = hex.length() / 2; - for (size_t i = 0; i < count; i++) - { - unsigned byte; - std::istringstream hex_byte(hex.substr(i * 2, 2)); - hex_byte >> std::hex >> byte; - data.push_back(static_cast(byte)); - } - - return data; -} - -std::string CToxProto::DataToHexString(std::vector data) -{ - std::ostringstream oss; - oss << std::hex << std::uppercase << std::setfill('0'); - for (size_t i = 0; i < data.size(); i++) - { - oss << std::setw(2) << static_cast(data[i]); - } - return oss.str(); -} - -std::string CToxProto::ToxAddressToId(std::string address) -{ - if (address.length() > TOX_CLIENT_ID_SIZE * 2) - { - address.erase(address.begin() + TOX_CLIENT_ID_SIZE * 2, address.end()); - } - return address; -} - bool CToxProto::IsFileExists(std::tstring path) { //return ::GetFileAttributes(fileName) != DWORD(-1) -- cgit v1.2.3