Browse Source

fix(core): Use node's TCP ports when connecting to TCP relay

Allows connecting to TCP relays that aren't acting as bootstrap nodes, and
connecting to TCP relays that have different or additional TCP ports compared
to UDP ports.
reviewable/pr6463/r5
Anthony Bilinski 4 years ago
parent
commit
e7e30ada8c
No known key found for this signature in database
GPG Key ID: 2AA8E0DA1B31FB3C
  1. 4
      src/core/core.cpp
  2. 3
      src/core/dhtserver.cpp
  3. 2
      src/core/dhtserver.h
  4. 42
      src/net/bootstrapnodeupdater.cpp

4
src/core/core.cpp

@ -846,7 +846,9 @@ void Core::bootstrapDht()
PARSE_ERR(error); PARSE_ERR(error);
} }
if (dhtServer.statusTcp) { if (dhtServer.statusTcp) {
tox_add_tcp_relay(tox.get(), address.constData(), dhtServer.udpPort, pkPtr, &error); const auto ports = dhtServer.tcpPorts.size();
const auto tcpPort = rand() % ports;
tox_add_tcp_relay(tox.get(), address.constData(), tcpPort, pkPtr, &error);
PARSE_ERR(error); PARSE_ERR(error);
} }

3
src/core/dhtserver.cpp

@ -33,7 +33,8 @@ bool DhtServer::operator==(const DhtServer& other) const
&& ipv6 == other.ipv6 && ipv6 == other.ipv6
&& maintainer == other.maintainer && maintainer == other.maintainer
&& userId == other.userId && userId == other.userId
&& udpPort == other.udpPort); && udpPort == other.udpPort
&& tcpPorts == other.tcpPorts);
} }
/** /**

2
src/core/dhtserver.h

@ -20,6 +20,7 @@
#pragma once #pragma once
#include <QString> #include <QString>
#include <vector>
struct DhtServer struct DhtServer
{ {
@ -30,6 +31,7 @@ struct DhtServer
QString maintainer; QString maintainer;
QString userId; QString userId;
quint16 udpPort; quint16 udpPort;
std::vector<uint16_t> tcpPorts;
bool operator==(const DhtServer& other) const; bool operator==(const DhtServer& other) const;
bool operator!=(const DhtServer& other) const; bool operator!=(const DhtServer& other) const;

42
src/net/bootstrapnodeupdater.cpp

@ -29,6 +29,9 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QRegularExpression> #include <QRegularExpression>
#include <QJsonArray>
#include <cstdint>
namespace NodeFields { namespace NodeFields {
const QLatin1String status_udp{"status_udp"}; const QLatin1String status_udp{"status_udp"};
@ -38,9 +41,8 @@ const QLatin1String ipv6{"ipv6"};
const QLatin1String public_key{"public_key"}; const QLatin1String public_key{"public_key"};
const QLatin1String udp_port{"port"}; const QLatin1String udp_port{"port"};
const QLatin1String maintainer{"maintainer"}; const QLatin1String maintainer{"maintainer"};
// TODO(sudden6): make use of this field once we differentiate between TCP nodes, and bootstrap nodes
const QLatin1String tcp_ports{"tcp_ports"}; const QLatin1String tcp_ports{"tcp_ports"};
const QStringList neededFields{status_udp, status_tcp, ipv4, ipv6, public_key, udp_port, maintainer}; const QStringList neededFields{status_udp, status_tcp, ipv4, ipv6, public_key, udp_port, tcp_ports, maintainer};
} // namespace NodeFields } // namespace NodeFields
namespace { namespace {
@ -63,13 +65,22 @@ void jsonNodeToDhtServer(const QJsonObject& node, QList<DhtServer>& outList)
return; return;
} }
// only use nodes that provide at least UDP connection
if (!node[NodeFields::status_udp].toBool(false)) {
return;
}
const QString public_key = node[NodeFields::public_key].toString({}); const QString public_key = node[NodeFields::public_key].toString({});
const auto udp_port = node[NodeFields::udp_port].toInt(-1); const auto udp_port = node[NodeFields::udp_port].toInt(-1);
const auto status_udp = node[NodeFields::status_udp].toBool(false);
const auto status_tcp = node[NodeFields::status_tcp].toBool(false);
const QString maintainer = node[NodeFields::maintainer].toString({});
std::vector<uint16_t> tcp_ports;
const auto jsonTcpPorts = node[NodeFields::tcp_ports].toArray();
for (int i = 0; i < jsonTcpPorts.count(); ++i) {
const auto port = jsonTcpPorts.at(i).toInt();
if (port < 1 || port > std::numeric_limits<uint16_t>::max()) {
qDebug () << "Invalid TCP port in nodes list:" << port;
return;
}
tcp_ports.emplace_back(static_cast<uint16_t>(port));
}
// nodes.tox.chat doesn't use empty strings for empty addresses // nodes.tox.chat doesn't use empty strings for empty addresses
QString ipv6_address = node[NodeFields::ipv6].toString({}); QString ipv6_address = node[NodeFields::ipv6].toString({});
@ -86,7 +97,13 @@ void jsonNodeToDhtServer(const QJsonObject& node, QList<DhtServer>& outList)
qWarning() << "Both ipv4 and ipv4 addresses are empty for" << public_key; qWarning() << "Both ipv4 and ipv4 addresses are empty for" << public_key;
} }
const QString maintainer = node[NodeFields::maintainer].toString({}); if (status_udp && udp_port == -1) {
qWarning() << "UDP enabled but no UDP port for" << public_key;
}
if (status_tcp && tcp_ports.empty()) {
qWarning() << "TCP enabled but no TCP ports for:" << public_key;
}
if (udp_port < 1 || udp_port > std::numeric_limits<uint16_t>::max()) { if (udp_port < 1 || udp_port > std::numeric_limits<uint16_t>::max()) {
qDebug() << "Invalid port in nodes list:" << udp_port; qDebug() << "Invalid port in nodes list:" << udp_port;
@ -101,7 +118,8 @@ void jsonNodeToDhtServer(const QJsonObject& node, QList<DhtServer>& outList)
DhtServer server; DhtServer server;
server.statusUdp = true; server.statusUdp = true;
server.statusTcp = node[NodeFields::status_udp].toBool(false); server.statusTcp = status_tcp;
server.tcpPorts = tcp_ports;
server.userId = public_key; server.userId = public_key;
server.udpPort = udp_port_u16; server.udpPort = udp_port_u16;
server.maintainer = maintainer; server.maintainer = maintainer;
@ -167,6 +185,12 @@ QByteArray serialize(QList<DhtServer> nodes)
nodeJson.insert(NodeFields::public_key, node.userId); nodeJson.insert(NodeFields::public_key, node.userId);
nodeJson.insert(NodeFields::udp_port, node.udpPort); nodeJson.insert(NodeFields::udp_port, node.udpPort);
nodeJson.insert(NodeFields::maintainer, node.maintainer); nodeJson.insert(NodeFields::maintainer, node.maintainer);
QJsonArray tcp_ports;
for (size_t i = 0; i < node.tcpPorts.size(); ++i) {
tcp_ports.push_back(node.tcpPorts.at(i));
}
nodeJson.insert(NodeFields::tcp_ports, tcp_ports);
jsonNodes.append(nodeJson); jsonNodes.append(nodeJson);
} }
QJsonObject rootObj; QJsonObject rootObj;

Loading…
Cancel
Save