summaryrefslogtreecommitdiff
path: root/protocols/Tox/src/tox_bootstrap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Tox/src/tox_bootstrap.cpp')
-rw-r--r--protocols/Tox/src/tox_bootstrap.cpp181
1 files changed, 181 insertions, 0 deletions
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);
+}