summaryrefslogtreecommitdiff
path: root/protocols/Tox/src/tox_connection.cpp
blob: 41fca21d6ea39241bee6567381a2ae9b36d8f0b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "stdafx.h"

bool CToxProto::IsOnline()
{
	return m_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);

		UpdateStatusMenu(NULL, NULL);

		LoadFriendList(tox);
		return;
	}

	int maxConnectRetries = getByte("MaxConnectRetries", TOX_MAX_CONNECT_RETRIES);
	if (m_iStatus++ > maxConnectRetries) {
		SetStatus(ID_STATUS_OFFLINE);
		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr, LOGINERR_NONETWORK);
		debugLogA(__FUNCTION__": failed to connect to DHT");
		return;
	}
}

void CToxProto::CheckConnection(Tox *tox, int &retriesCount)
{
	int maxReconnectRetries = getByte("MaxReconnectRetries", TOX_MAX_RECONNECT_RETRIES);
	TOX_CONNECTION connectionStatus = tox_self_get_connection_status(tox);
	if (connectionStatus != TOX_CONNECTION_NONE) {
		if (retriesCount < maxReconnectRetries) {
			debugLogA(__FUNCTION__": restored connection with DHT");
			retriesCount = maxReconnectRetries;
		}
	}
	else {
		if (retriesCount == maxReconnectRetries) {
			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(MODULE ": CheckingThread");

	debugLogA(__FUNCTION__": entering");

	CToxThread *thread = (CToxThread*)arg;
	int retriesCount = getByte("MaxReconnectRetries", TOX_MAX_RECONNECT_RETRIES);
	while (!thread->IsTerminated()) {
		if (m_iStatus < ID_STATUS_ONLINE)
			TryConnect(thread->Tox());
		else
			CheckConnection(thread->Tox(), retriesCount);

		WaitForSingleObject(hTerminateEvent, TOX_CHECKING_INTERVAL);
	}

	hCheckingThread = nullptr;

	debugLogA(__FUNCTION__": leaving");
}

void CToxProto::PollingThread(void*)
{
	Thread_SetName(MODULE ": PollingThread");

	debugLogA(__FUNCTION__": entering");

	Tox_Options *options = GetToxOptions();
	if (!options) {
		SetStatus(ID_STATUS_OFFLINE);
		ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, nullptr);
		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);

	m_toxThread = &toxThread;
	InitToxCore(toxThread.Tox());
	BootstrapNodes(toxThread.Tox());
	hCheckingThread = ForkThreadEx(&CToxProto::CheckingThread, &toxThread, nullptr);

	while (!toxThread.IsTerminated()) {
		tox_iterate(toxThread.Tox(), this);
		uint32_t interval = tox_iteration_interval(toxThread.Tox());
		interval = interval 
			? interval
			: TOX_DEFAULT_INTERVAL;
		WaitForSingleObject(hTerminateEvent, interval);
	}

	SetEvent(hTerminateEvent);
	WaitForSingleObject(hCheckingThread, TOX_CHECKING_INTERVAL);

	UninitToxCore(toxThread.Tox());
	m_toxThread = nullptr;
	hPollingThread = nullptr;

	debugLogA(__FUNCTION__": leaving");
}