2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-31 06:26:18 +00:00

Support work with different dcs on a single IP.

This commit is contained in:
John Preston
2018-04-24 12:46:27 +04:00
parent 909acb25fd
commit 7482025c10
16 changed files with 391 additions and 97 deletions

View File

@@ -180,7 +180,7 @@ ModExpFirst CreateModExp(
ModExpFirst result;
constexpr auto kMaxModExpFirstTries = 5;
for (auto tries = 0; tries != kMaxModExpFirstTries; ++tries) {
FillRandom(result.randomPower);
bytes::set_random(result.randomPower);
for (auto i = 0; i != ModExpFirst::kRandomPowerSize; ++i) {
result.randomPower[i] ^= randomSeed[i];
}
@@ -303,6 +303,7 @@ QString Connection::transport() const {
Connection::~Connection() {
Expects(data == nullptr);
if (thread) {
waitTillFinish();
}
@@ -312,13 +313,21 @@ void ConnectionPrivate::createConn(bool createIPv4, bool createIPv6) {
destroyAllConnections();
if (createIPv4) {
QWriteLocker lock(&stateConnMutex);
_conn4 = AbstractConnection::create(_dcType, thread());
_conn4 = AbstractConnection::create(
*_connectionOptions,
_shiftedDcId,
_dcType,
thread());
connect(_conn4, SIGNAL(error(qint32)), this, SLOT(onError4(qint32)));
connect(_conn4, SIGNAL(receivedSome()), this, SLOT(onReceivedSome()));
}
if (createIPv6) {
QWriteLocker lock(&stateConnMutex);
_conn6 = AbstractConnection::create(_dcType, thread());
_conn6 = AbstractConnection::create(
*_connectionOptions,
_shiftedDcId,
_dcType,
thread());
connect(_conn6, SIGNAL(error(qint32)), this, SLOT(onError6(qint32)));
connect(_conn6, SIGNAL(receivedSome()), this, SLOT(onReceivedSome()));
}
@@ -440,8 +449,12 @@ QString ConnectionPrivate::transport() const {
if ((!_conn4 && !_conn6) || (_conn4 && _conn6) || (_state < 0)) {
return QString();
}
QString result = (_conn4 ? _conn4 : _conn6)->transport();
if (!result.isEmpty() && Global::TryIPv6()) result += (_conn4 ? "/IPv4" : "/IPv6");
Assert(_connectionOptions != nullptr);
auto result = (_conn4 ? _conn4 : _conn6)->transport();
if (!result.isEmpty() && _connectionOptions->useIPv6) {
result += (_conn4 ? "/IPv4" : "/IPv6");
}
return result;
}
@@ -783,8 +796,9 @@ void ConnectionPrivate::tryToSend() {
MTPInitConnection<mtpRequest> initWrapper;
int32 initSize = 0, initSizeInInts = 0;
if (needsLayer) {
auto systemLangCode = sessionData->systemLangCode();
auto cloudLangCode = sessionData->cloudLangCode();
Assert(_connectionOptions != nullptr);
auto systemLangCode = _connectionOptions->systemLangCode;
auto cloudLangCode = _connectionOptions->cloudLangCode;
auto langPack = "tdesktop";
auto deviceModel = (_dcType == DcType::Cdn) ? "n/a" : cApiDeviceModel();
auto systemVersion = (_dcType == DcType::Cdn) ? "n/a" : cApiSystemVersion();
@@ -996,16 +1010,28 @@ void ConnectionPrivate::restartNow() {
void ConnectionPrivate::connectToServer(bool afterConfig) {
if (_finished) {
DEBUG_LOG(("MTP Error: connectToServer() called for finished connection!"));
DEBUG_LOG(("MTP Error: "
"connectToServer() called for finished connection!"));
return;
}
auto hasKey = true;
{
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData) {
DEBUG_LOG(("MTP Error: "
"connectToServer() called for stopped connection!"));
return;
}
_connectionOptions = std::make_unique<ConnectionOptions>(
sessionData->connectionOptions());
hasKey = (sessionData->getKey() != nullptr);
}
auto bareDc = bareDcId(_shiftedDcId);
_dcType = _instance->dcOptions()->dcType(_shiftedDcId);
if (_dcType == DcType::MediaDownload) { // using media_only addresses only if key for this dc is already created
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData || !sessionData->getKey()) {
_dcType = DcType::Regular;
}
// Use media_only addresses only if key for this dc is already created.
if (_dcType == DcType::MediaDownload && !hasKey) {
_dcType = DcType::Regular;
} else if (_dcType == DcType::Cdn && !_instance->isKeysDestroyer()) {
if (!_instance->dcOptions()->hasCDNKeysForDc(bareDc)) {
requestCDNConfig();
@@ -1014,26 +1040,30 @@ void ConnectionPrivate::connectToServer(bool afterConfig) {
}
using Variants = DcOptions::Variants;
auto kIPv4 = Variants::IPv4;
auto kIPv6 = Variants::IPv6;
auto kTcp = Variants::Tcp;
auto kHttp = Variants::Http;
auto variants = _instance->dcOptions()->lookup(bareDc, _dcType);
auto noIPv4 = (_dcType == DcType::Temporary) ? (variants.data[kIPv4][kTcp].port == 0) : (variants.data[kIPv4][kHttp].port == 0);
auto noIPv6 = (_dcType == DcType::Temporary) ? true : (!Global::TryIPv6() || (variants.data[kIPv6][kHttp].port == 0));
const auto kIPv4 = Variants::IPv4;
const auto kIPv6 = Variants::IPv6;
const auto kTcp = Variants::Tcp;
const auto kHttp = Variants::Http;
const auto variants = _instance->dcOptions()->lookup(bareDc, _dcType);
const auto useIPv4 = (_dcType == DcType::Temporary) ? true : _connectionOptions->useIPv4;
const auto useIPv6 = (_dcType == DcType::Temporary) ? false : _connectionOptions->useIPv6;
const auto useTcp = (_dcType == DcType::Temporary) ? true : _connectionOptions->useTcp;
const auto useHttp = (_dcType == DcType::Temporary) ? false : _connectionOptions->useHttp;
auto noIPv4 = (_dcType == DcType::Temporary) ? (variants.data[kIPv4][kTcp].port == 0) : (!useIPv4 || (variants.data[kIPv4][kHttp].port == 0));
auto noIPv6 = (_dcType == DcType::Temporary) ? true : (!useIPv6 || (variants.data[kIPv6][kHttp].port == 0));
if (noIPv4 && noIPv6) {
if (_instance->isKeysDestroyer()) {
LOG(("MTP Error: DC %1 options for IPv4 over HTTP not found for auth key destruction!").arg(_shiftedDcId));
if (Global::TryIPv6() && noIPv6) LOG(("MTP Error: DC %1 options for IPv6 over HTTP not found for auth key destruction!").arg(_shiftedDcId));
if (useIPv6 && noIPv6) LOG(("MTP Error: DC %1 options for IPv6 over HTTP not found for auth key destruction!").arg(_shiftedDcId));
emit _instance->keyDestroyed(_shiftedDcId);
return;
} else if (afterConfig) {
LOG(("MTP Error: DC %1 options for IPv4 over HTTP not found right after config load!").arg(_shiftedDcId));
if (Global::TryIPv6() && noIPv6) LOG(("MTP Error: DC %1 options for IPv6 over HTTP not found right after config load!").arg(_shiftedDcId));
if (useIPv6 && noIPv6) LOG(("MTP Error: DC %1 options for IPv6 over HTTP not found right after config load!").arg(_shiftedDcId));
return restart();
}
DEBUG_LOG(("MTP Info: DC %1 options for IPv4 over HTTP not found, waiting for config").arg(_shiftedDcId));
if (Global::TryIPv6() && noIPv6) DEBUG_LOG(("MTP Info: DC %1 options for IPv6 over HTTP not found, waiting for config").arg(_shiftedDcId));
if (useIPv6 && noIPv6) DEBUG_LOG(("MTP Info: DC %1 options for IPv6 over HTTP not found, waiting for config").arg(_shiftedDcId));
connect(_instance, SIGNAL(configLoaded()), this, SLOT(onConfigLoaded()), Qt::UniqueConnection);
InvokeQueued(_instance, [instance = _instance] {
instance->requestConfig();
@@ -1064,9 +1094,17 @@ void ConnectionPrivate::connectToServer(bool afterConfig) {
_waitForConnectedTimer.start(_waitForConnected);
if (auto conn = _conn4) {
auto endpoint = DcOptions::Endpoint();
if (_connectionOptions->proxy.type == ProxyData::Type::Mtproto) {
endpoint.ip = _connectionOptions->proxy.host.toStdString();
endpoint.port = _connectionOptions->proxy.port;
endpoint.flags = MTPDdcOption::Flag::f_tcpo_only;
} else {
endpoint = variants.data[kIPv4][kTcp];
}
connect(conn, SIGNAL(connected()), this, SLOT(onConnected4()));
connect(conn, SIGNAL(disconnected()), this, SLOT(onDisconnected4()));
conn->connectTcp(variants.data[kIPv4][kTcp]);
conn->connectTcp(endpoint);
conn->connectHttp(variants.data[kIPv4][kHttp]);
}
if (auto conn = _conn6) {
@@ -1180,7 +1218,9 @@ void ConnectionPrivate::onPingSendForce() {
}
void ConnectionPrivate::onWaitReceivedFailed() {
if (Global::ConnectionType() != dbictAuto && Global::ConnectionType() != dbictTcpProxy) {
Expects(_connectionOptions != nullptr);
if (!_connectionOptions->useTcp) {
return;
}
@@ -2625,7 +2665,7 @@ void ConnectionPrivate::dhClientParamsSend() {
// gen rand 'b'
auto randomSeed = std::array<gsl::byte, ModExpFirst::kRandomPowerSize>();
openssl::FillRandom(randomSeed);
bytes::set_random(randomSeed);
auto g_b_data = CreateModExp(_authKeyData->g, _authKeyStrings->dh_prime, randomSeed);
if (g_b_data.modexp.empty()) {
LOG(("AuthKey Error: could not generate good g_b."));