Every session dialled a proxy on its own with nothing in between, so a cold start or a proxy switch opened one socket per session per account in the same millisecond. A public mtproxy answers about two parallel handshakes and silently drops the rest, which the client read back as client_hello_sent_no_server_hello or connected_no_mtproto_data across the whole batch - including on a dd-secret proxy that sends no ClientHello at all and therefore cannot be fingerprint-blocked. Replace the machinery that was supposed to prevent this with a rate limiter that actually does. ProxyDialLease keeps at most two unproven handshakes in flight per proxy server, spaces the rest apart and stretches the spacing after a run of attempts that proved nothing, so a blackholed proxy is no longer redialled by every session on its own eight second timer. Everything that reacted to failure by changing its own behaviour is gone: EndpointAdmissionArbiter, EndpointLivePool, ConnectionBroker, session_proxy_adapter, SessionProxyPort, HandshakeGate, open_scheduler, endpoint_health, adaptive_policy and ProxyRotationManager. A fingerprint filter is deterministic, so rotating emulated ClientHello profiles only hands the other side more of them, and escalated recipes (fragmentation, pacing) make the flow less browser-like rather than more - while the signal that drove the escalation could not tell a DPI box from a proxy refusing extra connections. The ClientHello templates themselves are untouched and the profile is now whatever the user configured, fixed. Also: ServerHello budget 2.5s -> 5s, mtproxy status reduces through the same ProxyConnectionStatus path as every other proxy type, and route memory is wired back up so an address that answered is dialled first and one that failed is dialled last. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
150 lines
3.7 KiB
C++
150 lines
3.7 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#pragma once
|
|
|
|
#include "base/object_ptr.h"
|
|
#include "base/timer.h"
|
|
#include "core/core_settings_proxy.h"
|
|
#include "mtproto/proxy/check.h"
|
|
#include "mtproto/proxy/data.h"
|
|
#include "mtproto/transport/connection_abstract.h"
|
|
|
|
#include <optional>
|
|
|
|
namespace Ui {
|
|
class Show;
|
|
class BoxContent;
|
|
class InputField;
|
|
class PortInput;
|
|
class PasswordInput;
|
|
class Checkbox;
|
|
template <typename Enum>
|
|
class RadioenumGroup;
|
|
template <typename Enum>
|
|
class Radioenum;
|
|
} // namespace Ui
|
|
|
|
namespace Main {
|
|
class Account;
|
|
} // namespace Main
|
|
|
|
namespace Window {
|
|
class SessionController;
|
|
} // namespace Window
|
|
|
|
class ProxiesBoxController {
|
|
public:
|
|
using ProxyData = MTP::ProxyData;
|
|
using Type = ProxyData::Type;
|
|
|
|
explicit ProxiesBoxController(not_null<Main::Account*> account);
|
|
|
|
static void ShowApplyConfirmation(
|
|
Window::SessionController *controller,
|
|
Type type,
|
|
const QMap<QString, QString> &fields);
|
|
|
|
static object_ptr<Ui::BoxContent> CreateOwningBox(
|
|
not_null<Main::Account*> account,
|
|
const QString &highlightId = QString());
|
|
static void Show(
|
|
not_null<Window::SessionController*> controller,
|
|
const QString &highlightId = QString());
|
|
object_ptr<Ui::BoxContent> create(const QString &highlightId = QString());
|
|
|
|
enum class ItemState {
|
|
Unknown,
|
|
Connecting,
|
|
Online,
|
|
Checking,
|
|
Available,
|
|
Unavailable
|
|
};
|
|
struct ItemView {
|
|
int id = 0;
|
|
QString type;
|
|
QString host;
|
|
uint32 port = 0;
|
|
int ping = 0;
|
|
bool selected = false;
|
|
bool deleted = false;
|
|
bool supportsShare = false;
|
|
bool supportsCalls = false;
|
|
ItemState state = ItemState::Unknown;
|
|
MTP::ProxyCheckStatus progressStatus = MTP::ProxyCheckStatus::Idle;
|
|
QString statusText;
|
|
};
|
|
|
|
void deleteItem(int id);
|
|
void deleteItems();
|
|
void restoreItem(int id);
|
|
void shareItem(int id, bool qr);
|
|
void shareItems();
|
|
void checkItem(int id);
|
|
void applyItem(int id);
|
|
void reorderItems(int oldPosition, int newPosition);
|
|
object_ptr<Ui::BoxContent> editItemBox(int id);
|
|
object_ptr<Ui::BoxContent> addNewItemBox();
|
|
bool setProxySettings(ProxyData::Settings value);
|
|
void setProxyForCalls(bool enabled);
|
|
void setTryIPv6(bool enabled);
|
|
void setFastWarmup(bool enabled);
|
|
rpl::producer<ProxyData::Settings> proxySettingsValue() const;
|
|
|
|
[[nodiscard]] bool contains(const ProxyData &proxy) const;
|
|
void addNewItem(const ProxyData &proxy);
|
|
|
|
rpl::producer<ItemView> views() const;
|
|
|
|
rpl::producer<bool> listShareableChanges() const;
|
|
|
|
~ProxiesBoxController();
|
|
|
|
private:
|
|
using Checker = MTP::ProxyCheckConnection;
|
|
struct Item {
|
|
int id = 0;
|
|
ProxyData data;
|
|
bool deleted = false;
|
|
Checker checker;
|
|
Checker checkerv6;
|
|
ItemState state = ItemState::Unknown;
|
|
MTP::ProxyCheckStatus progressStatus = MTP::ProxyCheckStatus::Idle;
|
|
int ping = 0;
|
|
};
|
|
|
|
std::vector<Item>::iterator findById(int id);
|
|
std::vector<Item>::iterator findByProxy(const ProxyData &proxy);
|
|
void setDeleted(int id, bool deleted);
|
|
void updateView(const Item &item);
|
|
void share(const ProxyData &proxy, bool qr = false);
|
|
void saveDelayed();
|
|
void refreshChecker(Item &item);
|
|
|
|
void replaceItemWith(
|
|
std::vector<Item>::iterator which,
|
|
std::vector<Item>::iterator with);
|
|
void replaceItemValue(
|
|
std::vector<Item>::iterator which,
|
|
const ProxyData &proxy);
|
|
|
|
const not_null<Main::Account*> _account;
|
|
Core::SettingsProxy &_settings;
|
|
int _idCounter = 0;
|
|
std::vector<Item> _list;
|
|
rpl::event_stream<ItemView> _views;
|
|
base::Timer _saveTimer;
|
|
rpl::event_stream<ProxyData::Settings> _proxySettingsChanges;
|
|
std::shared_ptr<Ui::Show> _show;
|
|
|
|
ProxyData _lastSelectedProxy;
|
|
bool _lastSelectedProxyUsed = false;
|
|
|
|
rpl::lifetime _lifetime;
|
|
|
|
};
|