From 5de53491d607c38286b19989ba7182454f24fabc Mon Sep 17 00:00:00 2001
From: aunsane <aunsane@gmail.com>
Date: Wed, 15 Mar 2017 00:19:35 +0300
Subject: Tox: - tox_network.cpp splitted on two logical parts - tox network
 status checking moved to separated thread - started rejection of toxThread
 wrapper

---
 protocols/Tox/src/stdafx.h           |   4 +-
 protocols/Tox/src/tox_bootstrap.cpp  | 181 +++++++++++++++++++++
 protocols/Tox/src/tox_connection.cpp | 128 +++++++++++++++
 protocols/Tox/src/tox_contacts.cpp   |  41 ++---
 protocols/Tox/src/tox_core.cpp       |  52 +++---
 protocols/Tox/src/tox_messages.cpp   |  12 +-
 protocols/Tox/src/tox_network.cpp    | 303 -----------------------------------
 protocols/Tox/src/tox_options.cpp    |  36 ++---
 protocols/Tox/src/tox_profile.cpp    |   6 +-
 protocols/Tox/src/tox_proto.cpp      |  16 +-
 protocols/Tox/src/tox_proto.h        |  44 ++---
 protocols/Tox/src/tox_thread.h       |  54 +------
 protocols/Tox/src/tox_transfer.cpp   |  43 +++--
 13 files changed, 435 insertions(+), 485 deletions(-)
 create mode 100644 protocols/Tox/src/tox_bootstrap.cpp
 create mode 100644 protocols/Tox/src/tox_connection.cpp
 delete mode 100644 protocols/Tox/src/tox_network.cpp

(limited to 'protocols')

diff --git a/protocols/Tox/src/stdafx.h b/protocols/Tox/src/stdafx.h
index dee3d7f817..ccef2fd2cf 100644
--- a/protocols/Tox/src/stdafx.h
+++ b/protocols/Tox/src/stdafx.h
@@ -76,8 +76,8 @@ extern HINSTANCE g_hInstance;
 
 #define TOX_ERROR -1
 
-#define TOX_MAX_CONNECT_RETRIES 300
-#define TOX_MAX_DISCONNECT_RETRIES 300
+#define TOX_MAX_CONNECT_RETRIES 10
+#define TOX_MAX_DISCONNECT_RETRIES 10
 
 #define TOX_MAX_CALLS 1
 
diff --git a/protocols/Tox/src/tox_bootstrap.cpp b/protocols/Tox/src/tox_bootstrap.cpp
new file mode 100644
index 0000000000..167cad3a14
--- /dev/null
+++ b/protocols/Tox/src/tox_bootstrap.cpp
@@ -0,0 +1,181 @@
+#include "stdafx.h"
+
+void CToxProto::BootstrapUdpNode(Tox *tox, const char *address, int port, const char *hexKey)
+{
+	if (!toxThread)
+		return;
+
+	if (address == NULL || hexKey == NULL)
+		return;
+
+	ToxBinAddress binKey(hexKey, TOX_PUBLIC_KEY_SIZE * 2);
+	TOX_ERR_BOOTSTRAP error;
+	if (!tox_bootstrap(tox, address, port, binKey, &error))
+		debugLogA(__FUNCTION__ ": failed to bootstrap node %s:%d \"%s\" (%d)", address, port, hexKey, error);
+}
+
+void CToxProto::BootstrapTcpRelay(Tox *tox, const char *address, int port, const char *hexKey)
+{	
+	if (!toxThread)
+		return;
+
+	if (address == NULL || hexKey == NULL)
+		return;
+
+	ToxBinAddress binKey(hexKey, TOX_PUBLIC_KEY_SIZE * 2);
+	TOX_ERR_BOOTSTRAP error;
+	if (!tox_add_tcp_relay(tox, address, port, binKey, &error))
+		debugLogA(__FUNCTION__ ": failed to add tcp relay %s:%d \"%s\" (%d)", address, port, hexKey, error);
+}
+
+void CToxProto::BootstrapNodesFromDb(Tox *tox, bool isIPv6)
+{
+	char module[MAX_PATH];
+	mir_snprintf(module, "%s_Nodes", m_szModuleName);
+	int nodeCount = db_get_w(NULL, module, TOX_SETTINGS_NODE_COUNT, 0);
+	if (nodeCount > 0)
+	{
+		char setting[MAX_PATH];
+		for (int i = 0; i < nodeCount; i++)
+		{
+			mir_snprintf(setting, TOX_SETTINGS_NODE_IPV4, i);
+			ptrA address(db_get_sa(NULL, module, setting));
+			mir_snprintf(setting, TOX_SETTINGS_NODE_PORT, i);
+			int port = db_get_w(NULL, module, setting, 33445);
+			mir_snprintf(setting, TOX_SETTINGS_NODE_PKEY, i);
+			ptrA pubKey(db_get_sa(NULL, module, setting));
+			BootstrapUdpNode(tox, address, port, pubKey);
+			BootstrapTcpRelay(tox, address, port, pubKey);
+			if (isIPv6)
+			{
+				mir_snprintf(setting, TOX_SETTINGS_NODE_IPV6, i);
+				address = db_get_sa(NULL, module, setting);
+				BootstrapUdpNode(tox, address, port, pubKey);
+				BootstrapTcpRelay(tox, address, port, pubKey);
+			}
+		}
+	}
+}
+
+void CToxProto::BootstrapNodesFromJson(Tox *tox, bool isIPv6)
+{
+	ptrA json;
+
+	VARSW path(_A2W(TOX_JSON_PATH));
+
+	if (!IsFileExists(path))
+		UpdateNodes();
+
+	if (IsFileExists(path))
+	{
+		FILE *hFile = _wfopen(path, L"r");
+		if (hFile != NULL)
+		{
+			_fseeki64(hFile, 0, SEEK_END);
+			size_t size = _ftelli64(hFile);
+			json = (char*)mir_calloc(size);
+			rewind(hFile);
+			fread(json, sizeof(char), size, hFile);
+			fclose(hFile);
+		}
+	}
+
+	if (json)
+	{
+		JSONNode root = JSONNode::parse(json);
+		if (!root.empty())
+		{
+			JSONNode nodes = root.at("nodes").as_array();
+			for (size_t i = 0; i < nodes.size(); i++)
+			{
+				JSONNode node = nodes[i];
+
+				JSONNode address = node.at("ipv4");
+				JSONNode pubKey = node.at("public_key");
+
+				if (node.at("status_udp").as_bool())
+				{
+					int port = node.at("port").as_int();
+					BootstrapUdpNode(tox, address.as_string().c_str(), port, pubKey.as_string().c_str());
+					if (isIPv6)
+					{
+						address = node.at("ipv6");
+						BootstrapUdpNode(tox, address.as_string().c_str(), port, pubKey.as_string().c_str());
+					}
+				}
+
+				if (node.at("status_tcp").as_bool())
+				{
+					JSONNode tcpPorts = node.at("tcp_ports").as_array();
+					for (size_t i = 0; i < tcpPorts.size(); i++)
+					{
+						int port = tcpPorts[i].as_int();
+						BootstrapTcpRelay(tox, address.as_string().c_str(), port, pubKey.as_string().c_str());
+						if (isIPv6)
+						{
+							address = node.at("ipv6");
+							BootstrapTcpRelay(tox, address.as_string().c_str(), port, pubKey.as_string().c_str());
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+void CToxProto::BootstrapNodes(Tox *tox)
+{
+	debugLogA(__FUNCTION__": bootstraping DHT");
+	// bool isUdp = getBool("EnableUDP", 1);
+	bool isIPv6 = getBool("EnableIPv6", 0);
+	BootstrapNodesFromDb(tox, isIPv6);
+	BootstrapNodesFromJson(tox, isIPv6);
+}
+
+void CToxProto::UpdateNodes()
+{
+	HttpRequest request(REQUEST_GET, "https://nodes.tox.chat/json");
+	NLHR_PTR response(request.Send(m_hNetlibUser));
+	if (response->resultCode != HTTP_CODE_OK || !response->pData)
+	{
+		debugLogA(__FUNCTION__": failed to dowload tox.json");
+		return;
+	}
+
+	JSONNode root = JSONNode::parse(response->pData);
+	if (root.empty())
+	{
+		debugLogA(__FUNCTION__": failed to dowload tox.json");
+		return;
+	}
+
+	long lastUpdate = root.at("last_scan").as_int();
+	if (lastUpdate <= getDword("NodesUpdate", 0))
+		return;
+
+	ptrW path(mir_wstrdup((wchar_t*)VARSW(_A2W(TOX_JSON_PATH))));
+	if (!IsFileExists(path))
+	{
+		HANDLE hProfile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+		if (hProfile == NULL)
+		{
+			debugLogA(__FUNCTION__": failed to create tox.json");
+			return;
+		}
+		CloseHandle(hProfile);
+	}
+
+	FILE *hFile = _wfopen(path, L"w");
+	if (!hFile)
+	{
+		debugLogA(__FUNCTION__": failed to open tox.json");
+		return;
+	}
+
+	if (fwrite(response->pData, sizeof(char), response->dataLength, hFile) != (size_t)response->dataLength)
+		debugLogA(__FUNCTION__": failed to write tox.json");
+
+	fclose(hFile);
+
+	setDword("NodesUpdate", lastUpdate);
+}
diff --git a/protocols/Tox/src/tox_connection.cpp b/protocols/Tox/src/tox_connection.cpp
new file mode 100644
index 0000000000..2d78fd86fe
--- /dev/null
+++ b/protocols/Tox/src/tox_connection.cpp
@@ -0,0 +1,128 @@
+#include "stdafx.h"
+
+bool CToxProto::IsOnline()
+{
+	return toxThread && m_iStatus >= ID_STATUS_ONLINE;
+}
+
+void CToxProto::TryConnect(Tox *tox)
+{
+	TOX_CONNECTION connectionStatus = tox_self_get_connection_status(tox);
+	if (connectionStatus != TOX_CONNECTION_NONE)
+	{
+		debugLogA(__FUNCTION__": successfuly connected to DHT");
+
+		m_iStatus = m_iDesiredStatus;
+		ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus);
+		tox_self_set_status(tox, MirandaToToxStatus(m_iStatus));
+
+		debugLogA(__FUNCTION__": changing status from %i to %i", ID_STATUS_CONNECTING, m_iDesiredStatus);
+
+		LoadFriendList(tox);
+		return;
+	}
+
+	if (m_iStatus++ > TOX_MAX_CONNECT_RETRIES)
+	{
+		SetStatus(ID_STATUS_OFFLINE);
+		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NONETWORK);
+		debugLogA(__FUNCTION__": failed to connect to DHT");
+		return;
+	}
+}
+
+void CToxProto::CheckConnection(Tox *tox, int &retriesCount)
+{
+	TOX_CONNECTION connectionStatus = tox_self_get_connection_status(tox);
+	if (connectionStatus != TOX_CONNECTION_NONE)
+	{
+		if (retriesCount < TOX_MAX_DISCONNECT_RETRIES)
+		{
+			debugLogA(__FUNCTION__": restored connection with DHT");
+			retriesCount = TOX_MAX_DISCONNECT_RETRIES;
+		}
+	}
+	else
+	{
+		if (retriesCount == TOX_MAX_DISCONNECT_RETRIES)
+		{
+			retriesCount--;
+			debugLogA(__FUNCTION__": lost connection with DHT");
+		}
+		else if (!(--retriesCount))
+		{
+			debugLogA(__FUNCTION__": disconnected from DHT");
+			SetStatus(ID_STATUS_OFFLINE);
+			return;
+		}
+	}
+}
+
+void CToxProto::CheckingThread(void *arg)
+{
+	Thread_SetName("TOX: CheckingThread");
+
+	debugLogA(__FUNCTION__": entering");
+
+	Tox *tox = (Tox*)arg;
+	int retriesCount = TOX_MAX_DISCONNECT_RETRIES;
+	while (!isTerminated)
+	{
+		if (m_iStatus < ID_STATUS_ONLINE)
+			TryConnect(tox);
+		else
+			CheckConnection(tox, retriesCount);
+
+		WaitForSingleObject(hTerminateEvent, 1000);
+	}
+
+	debugLogA(__FUNCTION__": leaving");
+}
+
+void CToxProto::PollingThread(void*)
+{
+	Thread_SetName("TOX: PollingThread");
+
+	debugLogA(__FUNCTION__": entering");
+
+	Tox_Options *options = GetToxOptions();
+	if (!options)
+	{
+		SetStatus(ID_STATUS_OFFLINE);
+		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL);
+		debugLogA(__FUNCTION__": leaving");
+		return;
+	}
+
+	TOX_ERR_NEW error;
+	CToxThread toxThread(options, &error);
+	if (error != TOX_ERR_NEW_OK)
+	{
+		SetStatus(ID_STATUS_OFFLINE);
+		debugLogA(__FUNCTION__": failed to initialize tox core (%d)", error);
+		ShowNotification(TranslateT("Unable to initialize Tox core"), ToxErrorToString(error), MB_ICONERROR);
+		tox_options_free(options);
+		debugLogA(__FUNCTION__": leaving");
+		return;
+	}
+	tox_options_free(options);
+
+	this->toxThread = &toxThread;
+	InitToxCore(toxThread.Tox());
+	BootstrapNodes(toxThread.Tox());
+	ForkThread(&CToxProto::CheckingThread, toxThread.Tox());
+
+	while (!isTerminated)
+	{
+		tox_iterate(toxThread.Tox(), this);
+		uint32_t interval = tox_iteration_interval(toxThread.Tox());
+		interval = interval ? interval : 50;
+
+		WaitForSingleObject(hTerminateEvent, interval);
+	}
+
+	UninitToxCore(toxThread.Tox());
+	this->toxThread = NULL;
+
+	debugLogA(__FUNCTION__": leaving");
+}
\ No newline at end of file
diff --git a/protocols/Tox/src/tox_contacts.cpp b/protocols/Tox/src/tox_contacts.cpp
index a10fd03925..604f4259f5 100644
--- a/protocols/Tox/src/tox_contacts.cpp
+++ b/protocols/Tox/src/tox_contacts.cpp
@@ -37,14 +37,14 @@ MCONTACT CToxProto::GetContactFromAuthEvent(MEVENT hEvent)
 	return DbGetAuthEventContact(&dbei);
 }
 
-MCONTACT CToxProto::GetContact(const int friendNumber)
+MCONTACT CToxProto::GetContact(const Tox *tox, const int friendNumber)
 {
-	if (!toxThread)
+	if (!tox)
 		return NULL;
 
 	uint8_t data[TOX_PUBLIC_KEY_SIZE];
 	TOX_ERR_FRIEND_GET_PUBLIC_KEY error;
-	if (!tox_friend_get_public_key(toxThread->Tox(), friendNumber, data, &error))
+	if (!tox_friend_get_public_key(tox, friendNumber, data, &error))
 	{
 		debugLogA(__FUNCTION__": failed to get friend (%d) public key (%d)", friendNumber, error);
 		return NULL;
@@ -66,11 +66,14 @@ MCONTACT CToxProto::GetContact(const char *pubKey)
 	return hContact;
 }
 
-ToxHexAddress CToxProto::GetContactPublicKey(const int friendNumber)
+ToxHexAddress CToxProto::GetContactPublicKey(const Tox *tox, const int friendNumber)
 {
+	if (!tox)
+		return ToxHexAddress::Empty();
+
 	uint8_t data[TOX_PUBLIC_KEY_SIZE];
 	TOX_ERR_FRIEND_GET_PUBLIC_KEY error;
-	if (!tox_friend_get_public_key(toxThread->Tox(), friendNumber, data, &error))
+	if (!tox_friend_get_public_key(tox, friendNumber, data, &error))
 	{
 		debugLogA(__FUNCTION__": failed to get friend (%d) public key (%d)", friendNumber, error);
 		return ToxHexAddress::Empty();
@@ -122,11 +125,9 @@ uint32_t CToxProto::GetToxFriendNumber(MCONTACT hContact)
 	return friendNumber;
 }
 
-void CToxProto::LoadFriendList(void*)
+void CToxProto::LoadFriendList(Tox *tox)
 {
-	Thread_SetName("TOX: LoadFriendList");
-
-	size_t count = tox_self_get_friend_list_size(toxThread->Tox());
+	size_t count = tox_self_get_friend_list_size(tox);
 	if (count > 0)
 	{
 		uint32_t *friends = (uint32_t*)mir_alloc(count * sizeof(uint32_t));
@@ -136,7 +137,7 @@ void CToxProto::LoadFriendList(void*)
 		{
 			uint32_t friendNumber = friends[i];
 
-			ToxHexAddress pubKey = GetContactPublicKey(friendNumber);
+			ToxHexAddress pubKey = GetContactPublicKey(tox, friendNumber);
 			if (pubKey == ToxHexAddress::Empty())
 				continue;
 
@@ -212,7 +213,7 @@ INT_PTR CToxProto::OnGrantAuth(WPARAM hContact, LPARAM)
 	db_unset(hContact, "CList", "NotOnList");
 	delSetting(hContact, "Grant");
 
-	SaveToxProfile(toxThread);
+	SaveToxProfile(toxThread->Tox());
 
 	return 0;
 }
@@ -231,7 +232,7 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM)
 			debugLogA(__FUNCTION__": failed to delete friend (%d)", error);
 			return error;
 		}
-		SaveToxProfile(toxThread);
+		SaveToxProfile(toxThread->Tox());
 	}
 	/*else
 	{
@@ -269,11 +270,11 @@ void CToxProto::OnFriendRequest(Tox*, const uint8_t *pubKey, const uint8_t *mess
 	ProtoChainRecv(hContact, PSR_AUTH, 0, (LPARAM)&pre);
 }
 
-void CToxProto::OnFriendNameChange(Tox*, uint32_t friendNumber, const uint8_t *name, size_t length, void *arg)
+void CToxProto::OnFriendNameChange(Tox *tox, uint32_t friendNumber, const uint8_t *name, size_t length, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	if (MCONTACT hContact = proto->GetContact(friendNumber))
+	if (MCONTACT hContact = proto->GetContact(tox, friendNumber))
 	{
 		ptrA rawName((char*)mir_alloc(length + 1));
 		memcpy(rawName, name, length);
@@ -284,11 +285,11 @@ void CToxProto::OnFriendNameChange(Tox*, uint32_t friendNumber, const uint8_t *n
 	}
 }
 
-void CToxProto::OnStatusMessageChanged(Tox*, uint32_t friendNumber, const uint8_t *message, size_t length, void *arg)
+void CToxProto::OnStatusMessageChanged(Tox *tox, uint32_t friendNumber, const uint8_t *message, size_t length, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	if (MCONTACT hContact = proto->GetContact(friendNumber))
+	if (MCONTACT hContact = proto->GetContact(tox, friendNumber))
 	{
 		ptrA rawMessage((char*)mir_alloc(length + 1));
 		memcpy(rawMessage, message, length);
@@ -299,11 +300,11 @@ void CToxProto::OnStatusMessageChanged(Tox*, uint32_t friendNumber, const uint8_
 	}
 }
 
-void CToxProto::OnUserStatusChanged(Tox*, uint32_t friendNumber, TOX_USER_STATUS userstatus, void *arg)
+void CToxProto::OnUserStatusChanged(Tox *tox, uint32_t friendNumber, TOX_USER_STATUS userstatus, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact)
 	{
 		int status = proto->ToxToMirandaStatus(userstatus);
@@ -311,11 +312,11 @@ void CToxProto::OnUserStatusChanged(Tox*, uint32_t friendNumber, TOX_USER_STATUS
 	}
 }
 
-void CToxProto::OnConnectionStatusChanged(Tox*, uint32_t friendNumber, TOX_CONNECTION status, void *arg)
+void CToxProto::OnConnectionStatusChanged(Tox *tox, uint32_t friendNumber, TOX_CONNECTION status, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (!hContact)
 		return;
 
diff --git a/protocols/Tox/src/tox_core.cpp b/protocols/Tox/src/tox_core.cpp
index d18885fc9b..c040fa3426 100644
--- a/protocols/Tox/src/tox_core.cpp
+++ b/protocols/Tox/src/tox_core.cpp
@@ -48,27 +48,24 @@ Tox_Options* CToxProto::GetToxOptions()
 	return NULL;
 }
 
-bool CToxProto::InitToxCore(CToxThread *toxThread)
+void CToxProto::InitToxCore(Tox *tox)
 {
 	debugLogA(__FUNCTION__": initializing tox core");
 
-	if (toxThread == NULL)
-		return false;
-
-	tox_callback_friend_request(toxThread->Tox(), OnFriendRequest);
-	tox_callback_friend_message(toxThread->Tox(), OnFriendMessage);
-	tox_callback_friend_read_receipt(toxThread->Tox(), OnReadReceipt);
-	tox_callback_friend_typing(toxThread->Tox(), OnTypingChanged);
+	tox_callback_friend_request(tox, OnFriendRequest);
+	tox_callback_friend_message(tox, OnFriendMessage);
+	tox_callback_friend_read_receipt(tox, OnReadReceipt);
+	tox_callback_friend_typing(tox, OnTypingChanged);
 	//
-	tox_callback_friend_name(toxThread->Tox(), OnFriendNameChange);
-	tox_callback_friend_status_message(toxThread->Tox(), OnStatusMessageChanged);
-	tox_callback_friend_status(toxThread->Tox(), OnUserStatusChanged);
-	tox_callback_friend_connection_status(toxThread->Tox(), OnConnectionStatusChanged);
+	tox_callback_friend_name(tox, OnFriendNameChange);
+	tox_callback_friend_status_message(tox, OnStatusMessageChanged);
+	tox_callback_friend_status(tox, OnUserStatusChanged);
+	tox_callback_friend_connection_status(tox, OnConnectionStatusChanged);
 	// transfers
-	tox_callback_file_recv_control(toxThread->Tox(), OnFileRequest);
-	tox_callback_file_recv(toxThread->Tox(), OnFriendFile);
-	tox_callback_file_recv_chunk(toxThread->Tox(), OnDataReceiving);
-	tox_callback_file_chunk_request(toxThread->Tox(), OnFileSendData);
+	tox_callback_file_recv_control(tox, OnFileRequest);
+	tox_callback_file_recv(tox, OnFriendFile);
+	tox_callback_file_recv_chunk(tox, OnDataReceiving);
+	tox_callback_file_chunk_request(tox, OnFileSendData);
 	// group chats
 	//tox_callback_group_invite(tox, OnGroupChatInvite, this);
 	// a/v
@@ -87,7 +84,7 @@ bool CToxProto::InitToxCore(CToxThread *toxThread)
 	//}
 
 	uint8_t data[TOX_ADDRESS_SIZE];
-	tox_self_get_address(toxThread->Tox(), data);
+	tox_self_get_address(tox, data);
 	ToxHexAddress address(data);
 	setString(TOX_SETTINGS_ID, address);
 
@@ -98,33 +95,22 @@ bool CToxProto::InitToxCore(CToxThread *toxThread)
 	setWString("Nick", ptrW(Utf8DecodeW((char*)nick)));*/
 
 	ptrA nick(mir_utf8encodeW(ptrW(getWStringA("Nick"))));
-	tox_self_set_name(toxThread->Tox(), (uint8_t*)(char*)nick, mir_strlen(nick), &error);
+	tox_self_set_name(tox, (uint8_t*)(char*)nick, mir_strlen(nick), &error);
 	if (error != TOX_ERR_SET_INFO_OK)
-	{
 		debugLogA(__FUNCTION__": failed to set self name (%d)", error);
-		return NULL;
-	}
 
 	/*uint8_t statusMessage[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 };
 	tox_self_get_status_message(toxThread->Tox(), statusMessage);
 	setWString("StatusMsg", ptrW(Utf8DecodeW((char*)statusMessage)));*/
 
 	ptrA statusMessage(mir_utf8encodeW(ptrW(getWStringA("StatusMsg"))));
-	tox_self_set_status_message(toxThread->Tox(), (uint8_t*)(char*)statusMessage, mir_strlen(statusMessage), &error);
+	tox_self_set_status_message(tox, (uint8_t*)(char*)statusMessage, mir_strlen(statusMessage), &error);
 	if (error != TOX_ERR_SET_INFO_OK)
-	{
 		debugLogA(__FUNCTION__": failed to set self status message (%d)", error);
-		return NULL;
-	}
-
-	return true;
 }
 
-void CToxProto::UninitToxCore(CToxThread *toxThread)
+void CToxProto::UninitToxCore(Tox *tox)
 {
-	if (toxThread == NULL)
-		return;
-
-	CancelAllTransfers(toxThread);
-	SaveToxProfile(toxThread);
+	CancelAllTransfers(tox);
+	SaveToxProfile(tox);
 }
\ No newline at end of file
diff --git a/protocols/Tox/src/tox_messages.cpp b/protocols/Tox/src/tox_messages.cpp
index b1c6ef7d3d..471db3b23f 100644
--- a/protocols/Tox/src/tox_messages.cpp
+++ b/protocols/Tox/src/tox_messages.cpp
@@ -3,11 +3,11 @@
 /* MESSAGE RECEIVING */
 
 // incoming message flow
-void CToxProto::OnFriendMessage(Tox*, uint32_t friendNumber, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *arg)
+void CToxProto::OnFriendMessage(Tox *tox, uint32_t friendNumber, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact == NULL)
 		return;
 
@@ -94,11 +94,11 @@ int CToxProto::OnSendMessage(MCONTACT hContact, const char *szMessage)
 }
 
 // message is received by the other side
-void CToxProto::OnReadReceipt(Tox*, uint32_t friendNumber, uint32_t messageNumber, void *arg)
+void CToxProto::OnReadReceipt(Tox *tox, uint32_t friendNumber, uint32_t messageNumber, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact == NULL)
 		return;
 
@@ -177,11 +177,11 @@ int CToxProto::OnUserIsTyping(MCONTACT hContact, int type)
 	return 0;
 }
 
-void CToxProto::OnTypingChanged(Tox*, uint32_t friendNumber, bool isTyping, void *arg)
+void CToxProto::OnTypingChanged(Tox *tox, uint32_t friendNumber, bool isTyping, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	if (MCONTACT hContact = proto->GetContact(friendNumber))
+	if (MCONTACT hContact = proto->GetContact(tox, friendNumber))
 	{
 		int typingStatus = (isTyping ? PROTOTYPE_CONTACTTYPING_INFINITE : PROTOTYPE_CONTACTTYPING_OFF);
 		CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)typingStatus);
diff --git a/protocols/Tox/src/tox_network.cpp b/protocols/Tox/src/tox_network.cpp
deleted file mode 100644
index 893096039e..0000000000
--- a/protocols/Tox/src/tox_network.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-#include "stdafx.h"
-
-bool CToxProto::IsOnline()
-{
-	return toxThread && toxThread->IsConnected() && m_iStatus >= ID_STATUS_ONLINE;
-}
-
-void CToxProto::BootstrapUdpNode(CToxThread *toxThread, const char *address, int port, const char *hexKey)
-{
-	if (!toxThread)
-		return;
-
-	if (address == NULL || hexKey == NULL)
-		return;
-
-	ToxBinAddress binKey(hexKey, TOX_PUBLIC_KEY_SIZE * 2);
-	TOX_ERR_BOOTSTRAP error;
-	if (!tox_bootstrap(toxThread->Tox(), address, port, binKey, &error))
-		debugLogA(__FUNCTION__ ": failed to bootstrap node %s:%d \"%s\" (%d)", address, port, hexKey, error);
-}
-
-void CToxProto::BootstrapTcpRelay(CToxThread *toxThread, const char *address, int port, const char *hexKey)
-{	
-	if (!toxThread)
-		return;
-
-	if (address == NULL || hexKey == NULL)
-		return;
-
-	ToxBinAddress binKey(hexKey, TOX_PUBLIC_KEY_SIZE * 2);
-	TOX_ERR_BOOTSTRAP error;
-	if (!tox_add_tcp_relay(toxThread->Tox(), address, port, binKey, &error))
-		debugLogA(__FUNCTION__ ": failed to add tcp relay %s:%d \"%s\" (%d)", address, port, hexKey, error);
-}
-
-void CToxProto::BootstrapNodesFromDb(CToxThread *toxThread, bool isIPv6)
-{
-	char module[MAX_PATH];
-	mir_snprintf(module, "%s_Nodes", m_szModuleName);
-	int nodeCount = db_get_w(NULL, module, TOX_SETTINGS_NODE_COUNT, 0);
-	if (nodeCount > 0)
-	{
-		char setting[MAX_PATH];
-		for (int i = 0; i < nodeCount; i++)
-		{
-			mir_snprintf(setting, TOX_SETTINGS_NODE_IPV4, i);
-			ptrA address(db_get_sa(NULL, module, setting));
-			mir_snprintf(setting, TOX_SETTINGS_NODE_PORT, i);
-			int port = db_get_w(NULL, module, setting, 33445);
-			mir_snprintf(setting, TOX_SETTINGS_NODE_PKEY, i);
-			ptrA pubKey(db_get_sa(NULL, module, setting));
-			BootstrapUdpNode(toxThread, address, port, pubKey);
-			BootstrapTcpRelay(toxThread, address, port, pubKey);
-			if (isIPv6)
-			{
-				mir_snprintf(setting, TOX_SETTINGS_NODE_IPV6, i);
-				address = db_get_sa(NULL, module, setting);
-				BootstrapUdpNode(toxThread, address, port, pubKey);
-				BootstrapTcpRelay(toxThread, address, port, pubKey);
-			}
-		}
-	}
-}
-
-void CToxProto::BootstrapNodesFromJson(CToxThread *toxThread, bool isIPv6)
-{
-	ptrA json;
-
-	VARSW path(_A2W(TOX_JSON_PATH));
-
-	if (!IsFileExists(path))
-		UpdateNodes();
-
-	if (IsFileExists(path))
-	{
-		FILE *hFile = _wfopen(path, L"r");
-		if (hFile != NULL)
-		{
-			_fseeki64(hFile, 0, SEEK_END);
-			size_t size = _ftelli64(hFile);
-			json = (char*)mir_calloc(size);
-			rewind(hFile);
-			fread(json, sizeof(char), size, hFile);
-			fclose(hFile);
-		}
-	}
-
-	if (json)
-	{
-		JSONNode root = JSONNode::parse(json);
-		if (!root.empty())
-		{
-			JSONNode nodes = root.at("nodes").as_array();
-			for (size_t i = 0; i < nodes.size(); i++)
-			{
-				JSONNode node = nodes[i];
-
-				JSONNode address = node.at("ipv4");
-				JSONNode pubKey = node.at("public_key");
-
-				if (node.at("status_udp").as_bool())
-				{
-					int port = node.at("port").as_int();
-					BootstrapUdpNode(toxThread, address.as_string().c_str(), port, pubKey.as_string().c_str());
-					if (isIPv6)
-					{
-						address = node.at("ipv6");
-						BootstrapUdpNode(toxThread, address.as_string().c_str(), port, pubKey.as_string().c_str());
-					}
-				}
-
-				if (node.at("status_tcp").as_bool())
-				{
-					JSONNode tcpPorts = node.at("tcp_ports").as_array();
-					for (size_t i = 0; i < tcpPorts.size(); i++)
-					{
-						int port = tcpPorts[i].as_int();
-						BootstrapTcpRelay(toxThread, address.as_string().c_str(), port, pubKey.as_string().c_str());
-						if (isIPv6)
-						{
-							address = node.at("ipv6");
-							BootstrapTcpRelay(toxThread, address.as_string().c_str(), port, pubKey.as_string().c_str());
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-void CToxProto::BootstrapNodes(CToxThread *toxThread)
-{
-	debugLogA(__FUNCTION__": bootstraping DHT");
-	// bool isUdp = getBool("EnableUDP", 1);
-	bool isIPv6 = getBool("EnableIPv6", 0);
-	BootstrapNodesFromDb(toxThread, isIPv6);
-	BootstrapNodesFromJson(toxThread, isIPv6);
-}
-
-void CToxProto::UpdateNodes()
-{
-	HttpRequest request(REQUEST_GET, "https://nodes.tox.chat/json");
-	NLHR_PTR response(request.Send(m_hNetlibUser));
-	if (response->resultCode != HTTP_CODE_OK || !response->pData)
-	{
-		debugLogA(__FUNCTION__": failed to dowload tox.json");
-		return;
-	}
-
-	JSONNode root = JSONNode::parse(response->pData);
-	if (root.empty())
-	{
-		debugLogA(__FUNCTION__": failed to dowload tox.json");
-		return;
-	}
-
-	long lastUpdate = root.at("last_scan").as_int();
-	if (lastUpdate <= getDword("NodesUpdate", 0))
-		return;
-
-	ptrW path(mir_wstrdup((wchar_t*)VARSW(_A2W(TOX_JSON_PATH))));
-	if (!IsFileExists(path))
-	{
-		HANDLE hProfile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
-		if (hProfile == NULL)
-		{
-			debugLogA(__FUNCTION__": failed to create tox.json");
-			return;
-		}
-		CloseHandle(hProfile);
-	}
-
-	FILE *hFile = _wfopen(path, L"w");
-	if (!hFile)
-	{
-		debugLogA(__FUNCTION__": failed to open tox.json");
-		return;
-	}
-
-	if (fwrite(response->pData, sizeof(char), response->dataLength, hFile) != (size_t)response->dataLength)
-		debugLogA(__FUNCTION__": failed to write tox.json");
-
-	fclose(hFile);
-
-	setDword("NodesUpdate", lastUpdate);
-}
-
-void CToxProto::TryConnect()
-{
-	if (!toxThread)
-	{
-		return;
-	}
-
-	if (tox_self_get_connection_status(toxThread->Tox()) != TOX_CONNECTION_NONE)
-	{
-		toxThread->Connect();
-		debugLogA(__FUNCTION__": successfuly connected to DHT");
-
-		ForkThread(&CToxProto::LoadFriendList, NULL);
-
-		m_iStatus = m_iDesiredStatus;
-		ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus);
-		tox_self_set_status(toxThread->Tox(), MirandaToToxStatus(m_iStatus));
-		debugLogA(__FUNCTION__": changing status from %i to %i", ID_STATUS_CONNECTING, m_iDesiredStatus);
-	}
-	else if (m_iStatus++ > TOX_MAX_CONNECT_RETRIES)
-	{
-		SetStatus(ID_STATUS_OFFLINE);
-		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NONETWORK);
-		debugLogA(__FUNCTION__": failed to connect to DHT");
-	}
-}
-
-void CToxProto::CheckConnection(int &retriesCount)
-{
-	if (!toxThread || !toxThread->IsConnected())
-	{
-		TryConnect();
-	}
-	else if (tox_self_get_connection_status(toxThread->Tox()) != TOX_CONNECTION_NONE)
-	{
-		if (retriesCount < TOX_MAX_DISCONNECT_RETRIES)
-		{
-			debugLogA(__FUNCTION__": restored connection with DHT");
-			retriesCount = TOX_MAX_DISCONNECT_RETRIES;
-		}
-	}
-	else
-	{
-		if (retriesCount == TOX_MAX_DISCONNECT_RETRIES)
-		{
-			retriesCount--;
-			debugLogA(__FUNCTION__": lost connection with DHT");
-		}
-		/*else if (retriesCount % 50 == 0)
-		{
-			retriesCount--;
-			BootstrapNodes();
-		}*/
-		else if (!(--retriesCount))
-		{
-			toxThread->Disconnect();
-			debugLogA(__FUNCTION__": disconnected from DHT");
-			SetStatus(ID_STATUS_OFFLINE);
-		}
-	}
-}
-
-void CToxProto::PollingThread(void*)
-{
-	debugLogA(__FUNCTION__": entering");
-	Thread_SetName("TOX: PollingThread");
-
-	Tox_Options *options = GetToxOptions();
-	if (!options)
-	{
-		SetStatus(ID_STATUS_OFFLINE);
-		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL);
-		debugLogA(__FUNCTION__": leaving");
-		return;
-	}
-
-	TOX_ERR_NEW error;
-	CToxThread toxThread(options, &error);
-	if (error != TOX_ERR_NEW_OK)
-	{
-		SetStatus(ID_STATUS_OFFLINE);
-		debugLogA(__FUNCTION__": failed to initialize tox core (%d)", error);
-		ShowNotification(TranslateT("Unable to initialize Tox core"), ToxErrorToString(error), MB_ICONERROR);
-		tox_options_free(options);
-		debugLogA(__FUNCTION__": leaving");
-		return;
-	}
-	tox_options_free(options);
-
-	this->toxThread = &toxThread;
-
-	if (!InitToxCore(&toxThread))
-	{
-		UninitToxCore(&toxThread);
-		SetStatus(ID_STATUS_OFFLINE);
-		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
-		debugLogA(__FUNCTION__": leaving");
-		return;
-	}
-
-	int retriesCount = TOX_MAX_DISCONNECT_RETRIES;
-	BootstrapNodes(&toxThread);
-
-	while (!toxThread.IsTerminated())
-	{
-		CheckConnection(retriesCount);
-		toxThread.Iterate(this);
-	}
-
-	toxThread.Disconnect();
-	UninitToxCore(&toxThread);
-
-	this->toxThread = NULL;
-
-	debugLogA(__FUNCTION__": leaving");
-}
\ No newline at end of file
diff --git a/protocols/Tox/src/tox_options.cpp b/protocols/Tox/src/tox_options.cpp
index d57f42ebdd..22249057e8 100644
--- a/protocols/Tox/src/tox_options.cpp
+++ b/protocols/Tox/src/tox_options.cpp
@@ -64,7 +64,7 @@ void CToxOptionsMain::ProfileCreate_OnClick(CCtrlButton*)
 {
 	Tox_Options *options = NULL;
 	tox_options_default(options);
-	CToxThread toxThread(options);
+	Tox *tox = tox_new(options, NULL);
 	tox_options_free(options);
 
 	ptrW profilePath(m_proto->GetToxProfilePath());
@@ -79,27 +79,27 @@ void CToxOptionsMain::ProfileCreate_OnClick(CCtrlButton*)
 		CloseHandle(hProfile);
 	}
 
-	if (m_proto->InitToxCore(&toxThread))
-	{
-		ptrW group(m_group.GetText());
-		if (mir_wstrlen(group) > 0 && Clist_GroupExists(group))
-			Clist_GroupCreate(0, group);
+	m_proto->InitToxCore(tox);
 
-		m_proto->UninitToxCore(&toxThread);
+	ptrW group(m_group.GetText());
+	if (mir_wstrlen(group) > 0 && Clist_GroupExists(group))
+		Clist_GroupCreate(0, group);
 
-		m_toxAddress.Enable();
-		m_toxAddress.SetTextA(ptrA(m_proto->getStringA(TOX_SETTINGS_ID)));
+	m_proto->UninitToxCore(tox);
+	tox_kill(tox);
 
-		m_nickname.SetText(ptrW(m_proto->getWStringA("Nick")));
-		m_password.SetText(ptrW(m_proto->getWStringA("Password")));
-		m_group.SetText(ptrW(m_proto->getWStringA(TOX_SETTINGS_GROUP)));
+	m_toxAddress.Enable();
+	m_toxAddress.SetTextA(ptrA(m_proto->getStringA(TOX_SETTINGS_ID)));
 
-		ShowWindow(m_profileCreate.GetHwnd(), FALSE);
-		ShowWindow(m_profileImport.GetHwnd(), FALSE);
+	m_nickname.SetText(ptrW(m_proto->getWStringA("Nick")));
+	m_password.SetText(ptrW(m_proto->getWStringA("Password")));
+	m_group.SetText(ptrW(m_proto->getWStringA(TOX_SETTINGS_GROUP)));
 
-		ShowWindow(m_toxAddressCopy.GetHwnd(), TRUE);
-		ShowWindow(m_profileExport.GetHwnd(), TRUE);
-	}
+	ShowWindow(m_profileCreate.GetHwnd(), FALSE);
+	ShowWindow(m_profileImport.GetHwnd(), FALSE);
+
+	ShowWindow(m_toxAddressCopy.GetHwnd(), TRUE);
+	ShowWindow(m_profileExport.GetHwnd(), TRUE);
 }
 
 void CToxOptionsMain::ProfileImport_OnClick(CCtrlButton*)
@@ -199,7 +199,7 @@ void CToxOptionsMain::OnApply()
 		// todo: add checkbox
 		m_proto->setWString("Password", pass_ptrT(m_password.GetText()));
 
-		m_proto->SaveToxProfile(m_proto->toxThread);
+		m_proto->SaveToxProfile(m_proto->toxThread->Tox());
 	}
 }
 
diff --git a/protocols/Tox/src/tox_profile.cpp b/protocols/Tox/src/tox_profile.cpp
index c1d71bd40f..aec34c6381 100644
--- a/protocols/Tox/src/tox_profile.cpp
+++ b/protocols/Tox/src/tox_profile.cpp
@@ -97,16 +97,16 @@ bool CToxProto::LoadToxProfile(Tox_Options *options)
 	return false;
 }
 
-void CToxProto::SaveToxProfile(CToxThread *toxThread)
+void CToxProto::SaveToxProfile(Tox *tox)
 {
 	mir_cslock locker(profileLock);
 
 	if (!toxThread)
 		return;
 
-	size_t size = tox_get_savedata_size(toxThread->Tox());
+	size_t size = tox_get_savedata_size(tox);
 	uint8_t *data = (uint8_t*)mir_calloc(size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH);
-	tox_get_savedata(toxThread->Tox(), data);
+	tox_get_savedata(tox, data);
 
 	pass_ptrA password(mir_utf8encodeW(pass_ptrT(getWStringA("Password"))));
 	if (password && mir_strlen(password))
diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp
index 5209e3ef92..8090043ffe 100644
--- a/protocols/Tox/src/tox_proto.cpp
+++ b/protocols/Tox/src/tox_proto.cpp
@@ -2,8 +2,9 @@
 
 CToxProto::CToxProto(const char* protoName, const wchar_t* userName)
 	: PROTO<CToxProto>(protoName, userName),
-	hPollingThread(NULL), toxThread(NULL),
-	hOutDevice(NULL), hMessageProcess(1)
+	toxThread(NULL), isTerminated(false),
+	hCheckingThread(NULL), hPollingThread(NULL),
+	hMessageProcess(1)
 {
 	InitNetlib();
 
@@ -26,7 +27,9 @@ CToxProto::CToxProto(const char* protoName, const wchar_t* userName)
 	// nick
 	CreateProtoService(PS_SETMYNICKNAME, &CToxProto::SetMyNickname);
 
-	hAudioDialogs = WindowList_Create();
+	//hAudioDialogs = WindowList_Create();
+
+	hTerminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 }
 
 CToxProto::~CToxProto()
@@ -151,11 +154,8 @@ int CToxProto::SetStatus(int iNewStatus)
 	if (iNewStatus == ID_STATUS_OFFLINE)
 	{
 		// logout
-		if (toxThread)
-		{
-			toxThread->Stop();
-			toxThread = NULL;
-		}
+		isTerminated = true;
+		SetEvent(hTerminateEvent);
 
 		if (!Miranda_IsTerminated())
 		{
diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h
index 953452d01b..dea979efc0 100644
--- a/protocols/Tox/src/tox_proto.h
+++ b/protocols/Tox/src/tox_proto.h
@@ -72,10 +72,16 @@ private:
 	CToxThread *toxThread;
 	mir_cs profileLock;
 	wchar_t *accountName;
-	HANDLE hPollingThread;
+	
 	CTransferList transfers;
 	ULONG hMessageProcess;
 
+	bool isTerminated;
+	HANDLE hConnectingThread;
+	HANDLE hCheckingThread;
+	HANDLE hPollingThread;
+	HANDLE hTerminateEvent;
+
 	static HANDLE hProfileFolderPath;
 
 	// tox profile
@@ -83,30 +89,32 @@ private:
 	static wchar_t* GetToxProfilePath(const wchar_t *accountName);
 
 	bool LoadToxProfile(Tox_Options *options);
-	void SaveToxProfile(CToxThread *toxThread);
+	void SaveToxProfile(Tox *tox);
 
 	INT_PTR __cdecl OnCopyToxID(WPARAM, LPARAM);
 
 	// tox core
 	Tox_Options* GetToxOptions();
-	bool InitToxCore(CToxThread *toxThread);
-	void UninitToxCore(CToxThread *toxThread);
+	void InitToxCore(Tox *tox);
+	void UninitToxCore(Tox *tox);
 
-	// tox network
-	bool IsOnline();
-
-	void BootstrapUdpNode(CToxThread *toxThread, const char *address, int port, const char *pubKey);
-	void BootstrapTcpRelay(CToxThread *toxThread, const char *address, int port, const char *pubKey);
+	// tox bootstrap
+	void BootstrapUdpNode(Tox *tox, const char *address, int port, const char *pubKey);
+	void BootstrapTcpRelay(Tox *tox, const char *address, int port, const char *pubKey);
 
-	void BootstrapNodesFromDb(CToxThread *toxThread, bool isIPv6);
-	void BootstrapNodesFromJson(CToxThread *toxThread, bool isIPv6);
-	void BootstrapNodes(CToxThread *toxThread);
+	void BootstrapNodesFromDb(Tox *tox, bool isIPv6);
+	void BootstrapNodesFromJson(Tox *tox, bool isIPv6);
+	void BootstrapNodes(Tox *tox);
 
 	void UpdateNodes();
 
-	void TryConnect();
-	void CheckConnection(int &retriesCount);
+	// tox connection
+	bool IsOnline();
+
+	void TryConnect(Tox *tox);
+	void CheckConnection(Tox *tox, int &retriesCount);
 
+	void __cdecl CheckingThread(void*);
 	void __cdecl PollingThread(void*);
 
 	// accounts
@@ -152,10 +160,10 @@ private:
 	void SetContactStatus(MCONTACT hContact, WORD status);
 	void SetAllContactsStatus(WORD status);
 
-	MCONTACT GetContact(const int friendNumber);
+	MCONTACT GetContact(const Tox *tox, const int friendNumber);
 	MCONTACT GetContact(const char *pubKey);
 
-	ToxHexAddress GetContactPublicKey(const int friendNumber);
+	ToxHexAddress GetContactPublicKey(const Tox *tox, const int friendNumber);
 
 	MCONTACT AddContact(const char *address, const char *nick = NULL, const char *dnsId = NULL, bool isTemporary = false);
 
@@ -163,7 +171,7 @@ private:
 
 	uint32_t GetToxFriendNumber(MCONTACT hContact);
 
-	void __cdecl LoadFriendList(void*);
+	void LoadFriendList(Tox *tox);
 
 	INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam);
 	INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM);
@@ -244,7 +252,7 @@ private:
 
 	void PauseOutgoingTransfers(uint32_t friendNumber);
 	void ResumeIncomingTransfers(uint32_t friendNumber);
-	void CancelAllTransfers(CToxThread *toxThread);
+	void CancelAllTransfers(Tox *tox);
 
 	// avatars
 	wchar_t* GetAvatarFilePath(MCONTACT hContact = NULL);
diff --git a/protocols/Tox/src/tox_thread.h b/protocols/Tox/src/tox_thread.h
index a60d0246e3..ae0f4225f8 100644
--- a/protocols/Tox/src/tox_thread.h
+++ b/protocols/Tox/src/tox_thread.h
@@ -6,16 +6,10 @@ class CToxThread
 private:
 	Tox *tox;
 	ToxAV *toxAV;
-	bool isConnected;
-	bool isTerminated;
-
-	mir_cs toxLock;
-
-	mir_cs lock;
 
 public:
-	CToxThread(Tox_Options *options, TOX_ERR_NEW *error = NULL) : tox(NULL), toxAV(NULL),
-		isConnected(false), isTerminated(false)
+	CToxThread(Tox_Options *options, TOX_ERR_NEW *error = NULL)
+		: tox(NULL), toxAV(NULL)
 	{
 		tox = tox_new(options, error);
 	}
@@ -35,11 +29,6 @@ public:
 		}
 	}
 
-	mir_cslock Lock()
-	{
-		return mir_cslock(lock);
-	}
-
 	Tox* Tox()
 	{
 		return tox;
@@ -49,45 +38,6 @@ public:
 	{
 		return toxAV;
 	}
-
-	bool IsConnected() const
-	{
-		return tox && isConnected;
-	}
-
-	void Connect()
-	{
-		Lock();
-
-		isConnected = true;
-	}
-
-	void Disconnect()
-	{
-		Lock();
-
-		isConnected = false;
-	}
-
-	void Iterate(void* data)
-	{
-		{
-			mir_cslock lock(toxLock);
-			tox_iterate(tox, data);
-			//if (toxAV)
-			//	toxav_iterate(toxAV);
-		}
-		uint32_t interval = tox_iteration_interval(tox);
-		interval = interval ? interval : 50;
-		Sleep(interval);
-	}
-
-	bool IsTerminated() const
-	{
-		return !tox || isTerminated;
-	}
-
-	void Stop() { isTerminated = true; }
 };
 
 #endif //_TOX_THREAD_H_
\ No newline at end of file
diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp
index a85dcccc2e..d67d92ba9f 100644
--- a/protocols/Tox/src/tox_transfer.cpp
+++ b/protocols/Tox/src/tox_transfer.cpp
@@ -3,13 +3,13 @@
 /* FILE RECEIVING */
 
 // incoming transfer flow
-void CToxProto::OnFriendFile(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg)
+void CToxProto::OnFriendFile(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	ToxHexAddress pubKey = proto->GetContactPublicKey(friendNumber);
+	ToxHexAddress pubKey = proto->GetContactPublicKey(tox, friendNumber);
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact)
 	{
 		switch (kind)
@@ -28,7 +28,7 @@ void CToxProto::OnFriendFile(Tox*, uint32_t friendNumber, uint32_t fileNumber, u
 				proto->transfers.Add(transfer);
 
 				TOX_ERR_FILE_GET error;
-				tox_file_get_file_id(proto->toxThread->Tox(), friendNumber, fileNumber, transfer->hash, &error);
+				tox_file_get_file_id(tox, friendNumber, fileNumber, transfer->hash, &error);
 				if (error != TOX_ERR_FILE_GET_OK)
 				{
 					Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": unable to get avatar hash (%d) from %s(%d) cause (%d)", fileNumber, (const char*)pubKey, friendNumber, error);
@@ -109,7 +109,7 @@ int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const wchar_t **szFil
 	if (*action == FILERESUME_RENAME)
 		transfer->ChangeName(*szFilename);
 
-	ToxHexAddress pubKey = GetContactPublicKey(transfer->friendNumber);
+	ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), transfer->friendNumber);
 
 	wchar_t *mode = *action == FILERESUME_OVERWRITE ? L"wb" : L"ab";
 	if (!transfer->OpenFile(mode))
@@ -135,7 +135,7 @@ int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const wchar_t **szFil
 
 void CToxProto::OnTransferCompleted(FileTransferParam *transfer)
 {
-	ToxHexAddress pubKey = GetContactPublicKey(transfer->friendNumber);
+	ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), transfer->friendNumber);
 
 	debugLogA(__FUNCTION__": finised the transfer of file (%d) from %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
 	bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize;
@@ -153,11 +153,11 @@ void CToxProto::OnTransferCompleted(FileTransferParam *transfer)
 }
 
 // getting the file data
-void CToxProto::OnDataReceiving(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, const uint8_t *data, size_t length, void *arg)
+void CToxProto::OnDataReceiving(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, const uint8_t *data, size_t length, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	ToxHexAddress pubKey = proto->GetContactPublicKey(friendNumber);
+	ToxHexAddress pubKey = proto->GetContactPublicKey(tox, friendNumber);
 
 	FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
 	if (transfer == NULL)
@@ -173,11 +173,11 @@ void CToxProto::OnDataReceiving(Tox*, uint32_t friendNumber, uint32_t fileNumber
 		return;
 	}
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact == NULL)
 	{
 		Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": cannot find contact %s(%d)", (const char*)pubKey, friendNumber);
-		tox_file_control(proto->toxThread->Tox(), friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
+		tox_file_control(tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
 		return;
 	}
 
@@ -223,7 +223,7 @@ HANDLE CToxProto::OnSendFile(MCONTACT hContact, const wchar_t*, wchar_t **ppszFi
 	uint64_t fileSize = _ftelli64(hFile);
 	rewind(hFile);
 
-	ToxHexAddress pubKey = GetContactPublicKey(friendNumber);
+	ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
 
 	char *name = mir_utf8encodeW(fileName);
 	TOX_ERR_FILE_SEND sendError;
@@ -248,17 +248,17 @@ HANDLE CToxProto::OnSendFile(MCONTACT hContact, const wchar_t*, wchar_t **ppszFi
 	return (HANDLE)transfer;
 }
 
-void CToxProto::OnFileSendData(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, size_t length, void *arg)
+void CToxProto::OnFileSendData(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, size_t length, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	ToxHexAddress pubKey = proto->GetContactPublicKey(friendNumber);
+	ToxHexAddress pubKey = proto->GetContactPublicKey(tox, friendNumber);
 
 	FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
 	if (!transfer)
 	{
 		proto->debugLogA(__FUNCTION__": failed to find transfer (%d) to %s(%d)", fileNumber, (const char*)pubKey, friendNumber);
-		tox_file_control(proto->toxThread->Tox(), friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
+		tox_file_control(tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
 		return;
 	}
 
@@ -283,7 +283,7 @@ void CToxProto::OnFileSendData(Tox*, uint32_t friendNumber, uint32_t fileNumber,
 	{
 		proto->debugLogA(__FUNCTION__": failed to read from file (%d) to %s(%d)", fileNumber, (const char*)pubKey, friendNumber);
 		proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
-		tox_file_control(proto->toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
+		tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
 		mir_free(data);
 		return;
 	}
@@ -329,7 +329,7 @@ void CToxProto::PauseOutgoingTransfers(uint32_t friendNumber)
 		FileTransferParam *transfer = transfers.GetAt(i);
 		if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 0)
 		{
-			ToxHexAddress pubKey = GetContactPublicKey(friendNumber);
+			ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
 
 			debugLogA(__FUNCTION__": sending ask to pause the transfer of file (%d) to %s(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
 			TOX_ERR_FILE_CONTROL error;
@@ -350,7 +350,7 @@ void CToxProto::ResumeIncomingTransfers(uint32_t friendNumber)
 		FileTransferParam *transfer = transfers.GetAt(i);
 		if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 1)
 		{
-			ToxHexAddress pubKey = GetContactPublicKey(friendNumber);
+			ToxHexAddress pubKey = GetContactPublicKey(toxThread->Tox(), friendNumber);
 
 			debugLogA(__FUNCTION__": sending ask to resume the transfer of file (%d) from %s(%d) cause(%d)", transfer->fileNumber, (const char*)pubKey, transfer->friendNumber);
 			TOX_ERR_FILE_CONTROL error;
@@ -363,23 +363,22 @@ void CToxProto::ResumeIncomingTransfers(uint32_t friendNumber)
 	}
 }
 
-void CToxProto::CancelAllTransfers(CToxThread *toxThread)
+void CToxProto::CancelAllTransfers(Tox *tox)
 {
 	for (size_t i = 0; i < transfers.Count(); i++)
 	{
 		FileTransferParam *transfer = transfers.GetAt(i);
-		if (toxThread && toxThread->Tox())
-			tox_file_control(toxThread->Tox(), transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
+		tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
 		ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0);
 		transfers.Remove(transfer);
 	}
 }
 
-void CToxProto::OnFileRequest(Tox*, uint32_t friendNumber, uint32_t fileNumber, TOX_FILE_CONTROL control, void *arg)
+void CToxProto::OnFileRequest(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, TOX_FILE_CONTROL control, void *arg)
 {
 	CToxProto *proto = (CToxProto*)arg;
 
-	MCONTACT hContact = proto->GetContact(friendNumber);
+	MCONTACT hContact = proto->GetContact(tox, friendNumber);
 	if (hContact)
 	{
 		FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
-- 
cgit v1.2.3