1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "base/observer.h" 11 #include "base/bytes.h" 12 13 #include <QtCore/QReadWriteLock> 14 #include <string> 15 #include <vector> 16 #include <map> 17 #include <set> 18 19 namespace MTP { 20 namespace details { 21 class RSAPublicKey; 22 } // namespace details 23 24 enum class DcType { 25 Regular, 26 Temporary, 27 MediaCluster, 28 Cdn, 29 }; 30 31 enum class Environment : uchar { 32 Production, 33 Test, 34 }; 35 36 class DcOptions { 37 public: 38 using Flag = MTPDdcOption::Flag; 39 using Flags = MTPDdcOption::Flags; 40 struct Endpoint { EndpointEndpoint41 Endpoint( 42 DcId id, 43 Flags flags, 44 const std::string &ip, 45 int port, 46 const bytes::vector &secret) 47 : id(id) 48 , flags(flags) 49 , ip(ip) 50 , port(port) 51 , secret(secret) { 52 } 53 54 DcId id; 55 Flags flags; 56 std::string ip; 57 int port; 58 bytes::vector secret; 59 60 }; 61 62 explicit DcOptions(Environment environment); 63 DcOptions(const DcOptions &other); 64 ~DcOptions(); 65 66 [[nodiscard]] static bool ValidateSecret(bytes::const_span secret); 67 68 [[nodiscard]] Environment environment() const; 69 [[nodiscard]] bool isTestMode() const; 70 71 // construct methods don't notify "changed" subscribers. 72 bool constructFromSerialized(const QByteArray &serialized); 73 void constructFromBuiltIn(); 74 void constructAddOne( 75 int id, 76 Flags flags, 77 const std::string &ip, 78 int port, 79 const bytes::vector &secret); 80 QByteArray serialize() const; 81 82 [[nodiscard]] rpl::producer<DcId> changed() const; 83 [[nodiscard]] rpl::producer<> cdnConfigChanged() const; 84 void setFromList(const MTPVector<MTPDcOption> &options); 85 void addFromList(const MTPVector<MTPDcOption> &options); 86 void addFromOther(DcOptions &&options); 87 88 [[nodiscard]] std::vector<DcId> configEnumDcIds() const; 89 90 struct Variants { 91 enum Address { 92 IPv4 = 0, 93 IPv6 = 1, 94 AddressTypeCount = 2, 95 }; 96 enum Protocol { 97 Tcp = 0, 98 Http = 1, 99 ProtocolCount = 2, 100 }; 101 std::vector<Endpoint> data[AddressTypeCount][ProtocolCount]; 102 }; 103 [[nodiscard]] Variants lookup( 104 DcId dcId, 105 DcType type, 106 bool throughProxy) const; 107 [[nodiscard]] DcType dcType(ShiftedDcId shiftedDcId) const; 108 109 void setCDNConfig(const MTPDcdnConfig &config); 110 [[nodiscard]] bool hasCDNKeysForDc(DcId dcId) const; 111 [[nodiscard]] details::RSAPublicKey getDcRSAKey( 112 DcId dcId, 113 const QVector<MTPlong> &fingerprints) const; 114 115 // Debug feature for now. 116 bool loadFromFile(const QString &path); 117 bool writeToFile(const QString &path) const; 118 119 private: 120 bool applyOneGuarded( 121 DcId dcId, 122 Flags flags, 123 const std::string &ip, 124 int port, 125 const bytes::vector &secret); 126 static bool ApplyOneOption( 127 base::flat_map<DcId, std::vector<Endpoint>> &data, 128 DcId dcId, 129 Flags flags, 130 const std::string &ip, 131 int port, 132 const bytes::vector &secret); 133 static std::vector<DcId> CountOptionsDifference( 134 const base::flat_map<DcId, std::vector<Endpoint>> &a, 135 const base::flat_map<DcId, std::vector<Endpoint>> &b); 136 static void FilterIfHasWithFlag(Variants &variants, Flag flag); 137 138 [[nodiscard]] bool hasMediaOnlyOptionsFor(DcId dcId) const; 139 140 void processFromList(const QVector<MTPDcOption> &options, bool overwrite); 141 void computeCdnDcIds(); 142 143 void readBuiltInPublicKeys(); 144 145 class WriteLocker; 146 friend class WriteLocker; 147 148 class ReadLocker; 149 friend class ReadLocker; 150 151 const Environment _environment = Environment(); 152 base::flat_map<DcId, std::vector<Endpoint>> _data; 153 base::flat_set<DcId> _cdnDcIds; 154 base::flat_map<uint64, details::RSAPublicKey> _publicKeys; 155 base::flat_map< 156 DcId, 157 base::flat_map<uint64, details::RSAPublicKey>> _cdnPublicKeys; 158 mutable QReadWriteLock _useThroughLockers; 159 160 rpl::event_stream<DcId> _changed; 161 rpl::event_stream<> _cdnConfigChanged; 162 163 // True when we have overriden options from a .tdesktop-endpoints file. 164 bool _immutable = false; 165 166 }; 167 168 } // namespace MTP 169