Make all owned MTPD types immutable.

Remove custom refcounting in mtpData, use std::shared_ptr instead.
This commit is contained in:
John Preston 2017-03-09 21:13:55 +03:00
parent 839bf313cf
commit 3b373e236e
9 changed files with 7191 additions and 9237 deletions

View File

@ -2042,7 +2042,7 @@ mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) c
return result; return result;
} }
stream.avail_in = packedLen; stream.avail_in = packedLen;
stream.next_in = (Bytef*)&packed._string().v[0]; stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(packed.c_string().v.data()));
stream.avail_out = 0; stream.avail_out = 0;
while (!stream.avail_out) { while (!stream.avail_out) {
@ -2382,7 +2382,7 @@ void ConnectionPrivate::pqAnswered() {
return restart(); return restart();
} }
const auto &res_pq_data(res_pq.c_resPQ()); auto &res_pq_data = res_pq.c_resPQ();
if (res_pq_data.vnonce != _authKeyData->nonce) { if (res_pq_data.vnonce != _authKeyData->nonce) {
LOG(("AuthKey Error: received nonce <> sent nonce (in res_pq)!")); LOG(("AuthKey Error: received nonce <> sent nonce (in res_pq)!"));
DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&res_pq_data.vnonce, 16).str()).arg(Logs::mb(&_authKeyData->nonce, 16).str())); DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&res_pq_data.vnonce, 16).str()).arg(Logs::mb(&_authKeyData->nonce, 16).str()));
@ -2391,8 +2391,8 @@ void ConnectionPrivate::pqAnswered() {
static MTP::internal::RSAPublicKeys RSAKeys = MTP::internal::InitRSAPublicKeys(); static MTP::internal::RSAPublicKeys RSAKeys = MTP::internal::InitRSAPublicKeys();
const MTP::internal::RSAPublicKey *rsaKey = nullptr; const MTP::internal::RSAPublicKey *rsaKey = nullptr;
const auto &fingerPrints(res_pq.c_resPQ().vserver_public_key_fingerprints.c_vector().v); auto &fingerPrints = res_pq.c_resPQ().vserver_public_key_fingerprints.c_vector().v;
for (const auto &fingerPrint : fingerPrints) { for (auto &fingerPrint : fingerPrints) {
auto it = RSAKeys.constFind(static_cast<uint64>(fingerPrint.v)); auto it = RSAKeys.constFind(static_cast<uint64>(fingerPrint.v));
if (it != RSAKeys.cend()) { if (it != RSAKeys.cend()) {
rsaKey = &it.value(); rsaKey = &it.value();
@ -2401,7 +2401,7 @@ void ConnectionPrivate::pqAnswered() {
} }
if (!rsaKey) { if (!rsaKey) {
QStringList suggested, my; QStringList suggested, my;
for (const auto &fingerPrint : fingerPrints) { for (auto &fingerPrint : fingerPrints) {
suggested.push_back(QString("%1").arg(fingerPrint.v)); suggested.push_back(QString("%1").arg(fingerPrint.v));
} }
for (auto i = RSAKeys.cbegin(), e = RSAKeys.cend(); i != e; ++i) { for (auto i = RSAKeys.cbegin(), e = RSAKeys.cend(); i != e; ++i) {
@ -2412,49 +2412,54 @@ void ConnectionPrivate::pqAnswered() {
} }
_authKeyData->server_nonce = res_pq_data.vserver_nonce; _authKeyData->server_nonce = res_pq_data.vserver_nonce;
_authKeyData->new_nonce = rand_value<MTPint256>();
MTPP_Q_inner_data p_q_inner; auto &pq = res_pq_data.vpq.c_string().v;
MTPDp_q_inner_data &p_q_inner_data(p_q_inner._p_q_inner_data()); auto p = std::string();
p_q_inner_data.vnonce = _authKeyData->nonce; auto q = std::string();
p_q_inner_data.vserver_nonce = _authKeyData->server_nonce;
p_q_inner_data.vpq = res_pq_data.vpq;
const string &pq(res_pq_data.vpq.c_string().v);
string &p(p_q_inner_data.vp._string().v), &q(p_q_inner_data.vq._string().v);
if (!MTP::internal::parsePQ(pq, p, q)) { if (!MTP::internal::parsePQ(pq, p, q)) {
LOG(("AuthKey Error: could not factor pq!")); LOG(("AuthKey Error: could not factor pq!"));
DEBUG_LOG(("AuthKey Error: problematic pq: %1").arg(Logs::mb(&pq[0], pq.length()).str())); DEBUG_LOG(("AuthKey Error: problematic pq: %1").arg(Logs::mb(&pq[0], pq.length()).str()));
return restart(); return restart();
} }
_authKeyData->new_nonce = rand_value<MTPint256>(); auto p_q_inner = MTP_p_q_inner_data(res_pq_data.vpq, MTP_string(std::move(p)), MTP_string(std::move(q)), _authKeyData->nonce, _authKeyData->server_nonce, _authKeyData->new_nonce);
p_q_inner_data.vnew_nonce = _authKeyData->new_nonce; auto dhEncString = encryptPQInnerRSA(p_q_inner, rsaKey);
if (dhEncString.empty()) {
return restart();
}
connect(_conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered()));
DEBUG_LOG(("AuthKey Info: sending Req_DH_params..."));
MTPReq_DH_params req_DH_params; MTPReq_DH_params req_DH_params;
req_DH_params.vnonce = _authKeyData->nonce; req_DH_params.vnonce = _authKeyData->nonce;
req_DH_params.vserver_nonce = _authKeyData->server_nonce; req_DH_params.vserver_nonce = _authKeyData->server_nonce;
req_DH_params.vpublic_key_fingerprint = MTP_long(rsaKey->getFingerPrint()); req_DH_params.vpublic_key_fingerprint = MTP_long(rsaKey->getFingerPrint());
req_DH_params.vp = p_q_inner_data.vp; req_DH_params.vp = p_q_inner.c_p_q_inner_data().vp;
req_DH_params.vq = p_q_inner_data.vq; req_DH_params.vq = p_q_inner.c_p_q_inner_data().vq;
req_DH_params.vencrypted_data = MTP_string(std::move(dhEncString));
sendRequestNotSecure(req_DH_params);
}
string &dhEncString(req_DH_params.vencrypted_data._string().v); std::string ConnectionPrivate::encryptPQInnerRSA(const MTPP_Q_inner_data &data, const MTP::internal::RSAPublicKey *key) {
auto p_q_inner_size = data.innerLength();
uint32 p_q_inner_size = p_q_inner.innerLength(), encSize = (p_q_inner_size >> 2) + 6; auto encSize = (p_q_inner_size >> 2) + 6;
if (encSize >= 65) { if (encSize >= 65) {
mtpBuffer tmp; auto tmp = mtpBuffer();
tmp.reserve(encSize); tmp.reserve(encSize);
p_q_inner.write(tmp); data.write(tmp);
LOG(("AuthKey Error: too large data for RSA encrypt, size %1").arg(encSize * sizeof(mtpPrime))); LOG(("AuthKey Error: too large data for RSA encrypt, size %1").arg(encSize * sizeof(mtpPrime)));
DEBUG_LOG(("AuthKey Error: bad data for RSA encrypt %1").arg(Logs::mb(&tmp[0], tmp.size() * 4).str())); DEBUG_LOG(("AuthKey Error: bad data for RSA encrypt %1").arg(Logs::mb(&tmp[0], tmp.size() * 4).str()));
return restart(); // can't be 255-byte string return std::string(); // can't be 255-byte string
} }
mtpBuffer encBuffer; auto encBuffer = mtpBuffer();
encBuffer.reserve(65); // 260 bytes encBuffer.reserve(65); // 260 bytes
encBuffer.resize(6); encBuffer.resize(6);
encBuffer[0] = 0; encBuffer[0] = 0;
p_q_inner.write(encBuffer); data.write(encBuffer);
hashSha1(&encBuffer[6], p_q_inner_size, &encBuffer[1]); hashSha1(&encBuffer[6], p_q_inner_size, &encBuffer[1]);
if (encSize < 65) { if (encSize < 65) {
@ -2462,13 +2467,11 @@ void ConnectionPrivate::pqAnswered() {
memset_rand(&encBuffer[encSize], (65 - encSize) * sizeof(mtpPrime)); memset_rand(&encBuffer[encSize], (65 - encSize) * sizeof(mtpPrime));
} }
if (!rsaKey->encrypt(reinterpret_cast<const char*>(&encBuffer[0]) + 3, dhEncString)) { auto dhEncString = std::string();
return restart(); if (!key->encrypt(reinterpret_cast<const char*>(&encBuffer[0]) + 3, dhEncString)) {
return std::string();
} }
connect(_conn, SIGNAL(receivedData()), this, SLOT(dhParamsAnswered())); return dhEncString;
DEBUG_LOG(("AuthKey Info: sending Req_DH_params..."));
sendRequestNotSecure(req_DH_params);
} }
void ConnectionPrivate::dhParamsAnswered() { void ConnectionPrivate::dhParamsAnswered() {
@ -2598,15 +2601,11 @@ void ConnectionPrivate::dhClientParamsSend() {
return restart(); return restart();
} }
MTPClient_DH_Inner_Data client_dh_inner; auto g_b_string = std::string(256, ' ');
MTPDclient_DH_inner_data &client_dh_inner_data(client_dh_inner._client_DH_inner_data());
client_dh_inner_data.vnonce = _authKeyData->nonce;
client_dh_inner_data.vserver_nonce = _authKeyData->server_nonce;
client_dh_inner_data.vretry_id = _authKeyData->retry_id;
client_dh_inner_data.vg_b._string().v.resize(256);
// gen rand 'b' // gen rand 'b'
uint32 b[64], *g_b((uint32*)&client_dh_inner_data.vg_b._string().v[0]); uint32 b[64];
auto g_b = reinterpret_cast<uint32*>(&g_b_string[0]);
memset_rand(b, sizeof(b)); memset_rand(b, sizeof(b));
// count g_b and auth_key using openssl BIGNUM methods // count g_b and auth_key using openssl BIGNUM methods
@ -2620,21 +2619,33 @@ void ConnectionPrivate::dhClientParamsSend() {
memcpy(&_authKeyData->auth_key_aux_hash, auth_key_sha.data(), 8); memcpy(&_authKeyData->auth_key_aux_hash, auth_key_sha.data(), 8);
memcpy(&_authKeyData->auth_key_hash, auth_key_sha.data() + 12, 8); memcpy(&_authKeyData->auth_key_hash, auth_key_sha.data() + 12, 8);
auto client_dh_inner = MTP_client_DH_inner_data(_authKeyData->nonce, _authKeyData->server_nonce, _authKeyData->retry_id, MTP_string(std::move(g_b_string)));
auto sdhEncString = encryptClientDHInner(client_dh_inner);
connect(_conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered()));
MTPSet_client_DH_params req_client_DH_params; MTPSet_client_DH_params req_client_DH_params;
req_client_DH_params.vnonce = _authKeyData->nonce; req_client_DH_params.vnonce = _authKeyData->nonce;
req_client_DH_params.vserver_nonce = _authKeyData->server_nonce; req_client_DH_params.vserver_nonce = _authKeyData->server_nonce;
req_client_DH_params.vencrypted_data = MTP_string(std::move(sdhEncString));
string &sdhEncString(req_client_DH_params.vencrypted_data._string().v); DEBUG_LOG(("AuthKey Info: sending Req_client_DH_params..."));
sendRequestNotSecure(req_client_DH_params);
}
uint32 client_dh_inner_size = client_dh_inner.innerLength(), encSize = (client_dh_inner_size >> 2) + 5, encFullSize = encSize; std::string ConnectionPrivate::encryptClientDHInner(const MTPClient_DH_Inner_Data &data) {
auto client_dh_inner_size = data.innerLength();
auto encSize = (client_dh_inner_size >> 2) + 5;
auto encFullSize = encSize;
if (encSize & 0x03) { if (encSize & 0x03) {
encFullSize += 4 - (encSize & 0x03); encFullSize += 4 - (encSize & 0x03);
} }
mtpBuffer encBuffer; auto encBuffer = mtpBuffer();
encBuffer.reserve(encFullSize); encBuffer.reserve(encFullSize);
encBuffer.resize(5); encBuffer.resize(5);
client_dh_inner.write(encBuffer); data.write(encBuffer);
hashSha1(&encBuffer[5], client_dh_inner_size, &encBuffer[0]); hashSha1(&encBuffer[5], client_dh_inner_size, &encBuffer[0]);
if (encSize < encFullSize) { if (encSize < encFullSize) {
@ -2642,14 +2653,11 @@ void ConnectionPrivate::dhClientParamsSend() {
memset_rand(&encBuffer[encSize], (encFullSize - encSize) * sizeof(mtpPrime)); memset_rand(&encBuffer[encSize], (encFullSize - encSize) * sizeof(mtpPrime));
} }
sdhEncString.resize(encFullSize * 4); auto sdhEncString = std::string(encFullSize * 4, ' ');
aesIgeEncrypt(&encBuffer[0], &sdhEncString[0], encFullSize * sizeof(mtpPrime), _authKeyData->aesKey, _authKeyData->aesIV); aesIgeEncrypt(&encBuffer[0], &sdhEncString[0], encFullSize * sizeof(mtpPrime), _authKeyData->aesKey, _authKeyData->aesIV);
connect(_conn, SIGNAL(receivedData()), this, SLOT(dhClientParamsAnswered())); return sdhEncString;
DEBUG_LOG(("AuthKey Info: sending Req_client_DH_params..."));
sendRequestNotSecure(req_client_DH_params);
} }
void ConnectionPrivate::dhClientParamsAnswered() { void ConnectionPrivate::dhClientParamsAnswered() {

View File

@ -33,6 +33,7 @@ namespace internal {
class AbstractConnection; class AbstractConnection;
class ConnectionPrivate; class ConnectionPrivate;
class SessionData; class SessionData;
class RSAPublicKey;
class Thread : public QThread { class Thread : public QThread {
Q_OBJECT Q_OBJECT
@ -179,6 +180,9 @@ private:
bool setState(int32 state, int32 ifState = Connection::UpdateAlways); bool setState(int32 state, int32 ifState = Connection::UpdateAlways);
std::string encryptPQInnerRSA(const MTPP_Q_inner_data &data, const MTP::internal::RSAPublicKey *key);
std::string encryptClientDHInner(const MTPClient_DH_Inner_Data &data);
Instance *_instance = nullptr; Instance *_instance = nullptr;
mutable QReadWriteLock stateConnMutex; mutable QReadWriteLock stateConnMutex;

View File

@ -104,7 +104,7 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
throw Exception(QString("ungzip init, code: %1").arg(res)); throw Exception(QString("ungzip init, code: %1").arg(res));
} }
stream.avail_in = packedLen; stream.avail_in = packedLen;
stream.next_in = (Bytef*)&packed._string().v[0]; stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(packed.c_string().v.data()));
stream.avail_out = 0; stream.avail_out = 0;
while (!stream.avail_out) { while (!stream.avail_out) {
result.resize(result.size() + unpackedChunk); result.resize(result.size() + unpackedChunk);

View File

@ -29,7 +29,7 @@ namespace MTP {
using DcId = int32; using DcId = int32;
using ShiftedDcId = int32; using ShiftedDcId = int32;
} } // namespace MTP
using mtpPrime = int32; using mtpPrime = int32;
using mtpRequestId = int32; using mtpRequestId = int32;
@ -177,68 +177,23 @@ public:
class mtpData { class mtpData {
public: public:
mtpData() : cnt(1) {
}
mtpData(const mtpData &) : cnt(1) {
}
mtpData *incr() {
++cnt;
return this;
}
bool decr() {
return !--cnt;
}
bool needSplit() {
return (cnt > 1);
}
virtual mtpData *clone() = 0;
virtual ~mtpData() { virtual ~mtpData() {
} }
private:
uint32 cnt;
};
template <typename T>
class mtpDataImpl : public mtpData {
public:
virtual mtpData *clone() {
return new T(*(T*)this);
}
}; };
class mtpDataOwner { class mtpDataOwner {
public: public:
mtpDataOwner(const mtpDataOwner &v) : data(v.data ? v.data->incr() : 0) { mtpDataOwner(mtpDataOwner &&other) = default;
} mtpDataOwner(const mtpDataOwner &other) = default;
mtpDataOwner &operator=(const mtpDataOwner &v) { mtpDataOwner &operator=(mtpDataOwner &&other) = default;
setData(v.data ? v.data->incr() : v.data); mtpDataOwner &operator=(const mtpDataOwner &other) = default;
return *this;
}
~mtpDataOwner() {
if (data && data->decr()) delete data;
}
protected: protected:
explicit mtpDataOwner(mtpData *_data) : data(_data) { explicit mtpDataOwner(std::shared_ptr<const mtpData> &&data) : data(data) {
} }
void split() { std::shared_ptr<const mtpData> data;
if (data && data->needSplit()) {
mtpData *clone = data->clone();
if (data->decr()) delete data;
data = clone;
}
}
void setData(mtpData *_data) {
if (data != _data) {
if (data && data->decr()) delete data;
data = _data;
}
}
mtpData *data;
}; };
enum { enum {
@ -614,12 +569,14 @@ inline bool operator!=(const MTPdouble &a, const MTPdouble &b) {
return a.v != b.v; return a.v != b.v;
} }
class MTPDstring : public mtpDataImpl<MTPDstring> { class MTPDstring : public mtpData {
public: public:
MTPDstring() { MTPDstring() {
} }
MTPDstring(const std::string &val) : v(val) { MTPDstring(const std::string &val) : v(val) {
} }
MTPDstring(std::string &&val) : v(std::move(val)) {
}
MTPDstring(const QString &val) : v(val.toUtf8().constData()) { MTPDstring(const QString &val) : v(val.toUtf8().constData()) {
} }
MTPDstring(const QByteArray &val) : v(val.constData(), val.size()) { MTPDstring(const QByteArray &val) : v(val.constData(), val.size()) {
@ -628,24 +585,20 @@ public:
} }
std::string v; std::string v;
}; };
class MTPstring : private mtpDataOwner { class MTPstring : private mtpDataOwner {
public: public:
MTPstring() : mtpDataOwner(new MTPDstring()) { MTPstring() : mtpDataOwner(nullptr) {
} }
MTPstring(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string) : mtpDataOwner(0) { MTPstring(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string) : mtpDataOwner(0) {
read(from, end, cons); read(from, end, cons);
} }
MTPDstring &_string() {
t_assert(data != nullptr);
split();
return *(MTPDstring*)data;
}
const MTPDstring &c_string() const { const MTPDstring &c_string() const {
t_assert(data != nullptr); t_assert(data != nullptr);
return *(const MTPDstring*)data; return static_cast<const MTPDstring&>(*data);
} }
uint32 innerLength() const { uint32 innerLength() const {
@ -679,10 +632,8 @@ public:
} }
if (from > end) throw mtpErrorInsufficient(); if (from > end) throw mtpErrorInsufficient();
if (!data) setData(new MTPDstring()); auto string = std::string(reinterpret_cast<const char*>(buf), l);
MTPDstring &v(_string()); data = std::make_shared<MTPDstring>(std::move(string));
v.v.resize(l);
memcpy(&v.v[0], buf, l);
} }
void write(mtpBuffer &to) const { void write(mtpBuffer &to) const {
uint32 l = c_string().v.length(), s = l + ((l < 254) ? 1 : 4), was = to.size(); uint32 l = c_string().v.length(), s = l + ((l < 254) ? 1 : 4), was = to.size();
@ -705,23 +656,28 @@ public:
} }
private: private:
explicit MTPstring(MTPDstring *_data) : mtpDataOwner(_data) { explicit MTPstring(std::shared_ptr<const MTPDstring> &&data) : mtpDataOwner(std::move(data)) {
} }
friend MTPstring MTP_string(const std::string &v); friend MTPstring MTP_string(const std::string &v);
friend MTPstring MTP_string(std::string &&v);
friend MTPstring MTP_string(const QString &v); friend MTPstring MTP_string(const QString &v);
friend MTPstring MTP_string(const char *v); friend MTPstring MTP_string(const char *v);
friend MTPstring MTP_bytes(const QByteArray &v); friend MTPstring MTP_bytes(const QByteArray &v);
}; };
inline MTPstring MTP_string(const std::string &v) { inline MTPstring MTP_string(const std::string &v) {
return MTPstring(new MTPDstring(v)); return MTPstring(std::make_shared<MTPDstring>(v));
}
inline MTPstring MTP_string(std::string &&v) {
return MTPstring(std::make_shared<MTPDstring>(std::move(v)));
} }
inline MTPstring MTP_string(const QString &v) { inline MTPstring MTP_string(const QString &v) {
return MTPstring(new MTPDstring(v)); return MTPstring(std::make_shared<MTPDstring>(v));
} }
inline MTPstring MTP_string(const char *v) { inline MTPstring MTP_string(const char *v) {
return MTPstring(new MTPDstring(v)); return MTPstring(std::make_shared<MTPDstring>(v));
} }
MTPstring MTP_string(const QByteArray &v) = delete; MTPstring MTP_string(const QByteArray &v) = delete;
using MTPString = MTPBoxed<MTPstring>; using MTPString = MTPBoxed<MTPstring>;
@ -730,7 +686,7 @@ using MTPbytes = MTPstring;
using MTPBytes = MTPBoxed<MTPbytes>; using MTPBytes = MTPBoxed<MTPbytes>;
inline MTPbytes MTP_bytes(const QByteArray &v) { inline MTPbytes MTP_bytes(const QByteArray &v) {
return MTPbytes(new MTPDstring(v)); return MTPbytes(std::make_shared<MTPDstring>(v));
} }
inline bool operator==(const MTPstring &a, const MTPstring &b) { inline bool operator==(const MTPstring &a, const MTPstring &b) {
@ -751,7 +707,7 @@ inline QByteArray qba(const MTPstring &v) {
} }
template <typename T> template <typename T>
class MTPDvector : public mtpDataImpl<MTPDvector<T> > { class MTPDvector : public mtpData {
public: public:
MTPDvector() { MTPDvector() {
} }
@ -769,26 +725,21 @@ public:
template <typename T> template <typename T>
class MTPvector : private mtpDataOwner { class MTPvector : private mtpDataOwner {
public: public:
MTPvector() : mtpDataOwner(new MTPDvector<T>()) { MTPvector() : mtpDataOwner(nullptr) {
} }
MTPvector(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_vector) : mtpDataOwner(0) { MTPvector(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_vector) : mtpDataOwner(0) {
read(from, end, cons); read(from, end, cons);
} }
MTPDvector<T> &_vector() {
t_assert(data != nullptr);
split();
return *(MTPDvector<T>*)data;
}
const MTPDvector<T> &c_vector() const { const MTPDvector<T> &c_vector() const {
t_assert(data != nullptr); t_assert(data != nullptr);
return *(const MTPDvector<T>*)data; return static_cast<const MTPDvector<T>&>(*data);
} }
uint32 innerLength() const { uint32 innerLength() const {
uint32 result(sizeof(uint32)); uint32 result(sizeof(uint32));
for (typename VType::const_iterator i = c_vector().v.cbegin(), e = c_vector().v.cend(); i != e; ++i) { for_const (auto &item, c_vector().v) {
result += i->innerLength(); result += item.innerLength();
} }
return result; return result;
} }
@ -800,23 +751,22 @@ public:
if (cons != mtpc_vector) throw mtpErrorUnexpected(cons, "MTPvector"); if (cons != mtpc_vector) throw mtpErrorUnexpected(cons, "MTPvector");
uint32 count = (uint32)*(from++); uint32 count = (uint32)*(from++);
if (!data) setData(new MTPDvector<T>()); auto vector = QVector<T>();
MTPDvector<T> &v(_vector()); vector.reserve(count);
v.v.resize(0); for (auto i = 0; i != count; ++i) {
v.v.reserve(count); vector.push_back(T(from, end));
for (uint32 i = 0; i < count; ++i) {
v.v.push_back(T(from, end));
} }
data = std::make_shared<MTPDvector<T>>(std::move(vector));
} }
void write(mtpBuffer &to) const { void write(mtpBuffer &to) const {
to.push_back(c_vector().v.size()); to.push_back(c_vector().v.size());
for (typename VType::const_iterator i = c_vector().v.cbegin(), e = c_vector().v.cend(); i != e; ++i) { for_const (auto &item, c_vector().v) {
(*i).write(to); item.write(to);
} }
} }
private: private:
explicit MTPvector(MTPDvector<T> *_data) : mtpDataOwner(_data) { explicit MTPvector(std::shared_ptr<MTPDvector<T>> &&data) : mtpDataOwner(std::move(data)) {
} }
template <typename U> template <typename U>
@ -825,19 +775,25 @@ private:
friend MTPvector<U> MTP_vector(uint32 count, const U &value); friend MTPvector<U> MTP_vector(uint32 count, const U &value);
template <typename U> template <typename U>
friend MTPvector<U> MTP_vector(const QVector<U> &v); friend MTPvector<U> MTP_vector(const QVector<U> &v);
using VType = typename MTPDvector<T>::VType; template <typename U>
friend MTPvector<U> MTP_vector(QVector<U> &&v);
}; };
template <typename T> template <typename T>
inline MTPvector<T> MTP_vector(uint32 count) { inline MTPvector<T> MTP_vector(uint32 count) {
return MTPvector<T>(new MTPDvector<T>(count)); return MTPvector<T>(std::make_shared<MTPDvector<T>>(count));
} }
template <typename T> template <typename T>
inline MTPvector<T> MTP_vector(uint32 count, const T &value) { inline MTPvector<T> MTP_vector(uint32 count, const T &value) {
return MTPvector<T>(new MTPDvector<T>(count, value)); return MTPvector<T>(std::make_shared<MTPDvector<T>>(count, value));
} }
template <typename T> template <typename T>
inline MTPvector<T> MTP_vector(const QVector<T> &v) { inline MTPvector<T> MTP_vector(const QVector<T> &v) {
return MTPvector<T>(new MTPDvector<T>(v)); return MTPvector<T>(std::make_shared<MTPDvector<T>>(v));
}
template <typename T>
inline MTPvector<T> MTP_vector(QVector<T> &&v) {
return MTPvector<T>(std::make_shared<MTPDvector<T>>(std::move(v)));
} }
template <typename T> template <typename T>
using MTPVector = MTPBoxed<MTPvector<T>>; using MTPVector = MTPBoxed<MTPvector<T>>;
@ -866,7 +822,7 @@ struct MTPStringLogger {
} }
MTPStringLogger &add(const QString &data) { MTPStringLogger &add(const QString &data) {
QByteArray d = data.toUtf8(); auto d = data.toUtf8();
return add(d.constData(), d.size()); return add(d.constData(), d.size());
} }

View File

@ -573,7 +573,7 @@ for restype in typesList:
trivialConditions = data[7]; trivialConditions = data[7];
dataText = ''; dataText = '';
dataText += '\nclass MTPD' + name + ' : public mtpDataImpl<MTPD' + name + '> {\n'; # data class dataText += '\nclass MTPD' + name + ' : public mtpData {\n'; # data class
dataText += 'public:\n'; dataText += 'public:\n';
sizeList = []; sizeList = [];
@ -608,28 +608,20 @@ for restype in typesList:
dataText += '\tMTPD' + name + '() {\n\t}\n'; # default constructor dataText += '\tMTPD' + name + '() {\n\t}\n'; # default constructor
switchLines += '\t\tcase mtpc_' + name + ': '; # for by-type-id type constructor switchLines += '\t\tcase mtpc_' + name + ': '; # for by-type-id type constructor
if (len(prms) > len(trivialConditions)): if (len(prms) > len(trivialConditions)):
switchLines += 'setData(new MTPD' + name + '()); '; switchLines += 'data = std::make_shared<MTPD' + name + '>(); ';
withData = 1; withData = 1;
getters += '\n\tMTPD' + name + ' &_' + name + '() {\n'; # splitting getter getters += '\tconst MTPD' + name + ' &c_' + name + '() const;\n'; # const getter
constructsInline += 'inline const MTPD' + name + ' &MTP' + restype + '::c_' + name + '() const {\n';
if (withType): if (withType):
getters += '\t\tt_assert(data != nullptr && _type == mtpc_' + name + ');\n'; constructsInline += '\tt_assert(data != nullptr && _type == mtpc_' + name + ');\n';
else: else:
getters += '\t\tt_assert(data != nullptr);\n'; constructsInline += '\tt_assert(data != nullptr);\n';
getters += '\t\tsplit();\n'; constructsInline += '\treturn static_cast<const MTPD' + name + '&>(*data);\n';
getters += '\t\treturn *(MTPD' + name + '*)data;\n'; constructsInline += '}\n';
getters += '\t}\n';
getters += '\tconst MTPD' + name + ' &c_' + name + '() const {\n'; # const getter constructsText += '\texplicit MTP' + restype + '(std::shared_ptr<const MTPD' + name + '> &&data);\n'; # by-data type constructor
if (withType): constructsInline += 'inline MTP' + restype + '::MTP' + restype + '(std::shared_ptr<const MTPD' + name + '> &&data) : mtpDataOwner(std::move(data))';
getters += '\t\tt_assert(data != nullptr && _type == mtpc_' + name + ');\n';
else:
getters += '\t\tt_assert(data != nullptr);\n';
getters += '\t\treturn *(const MTPD' + name + '*)data;\n';
getters += '\t}\n';
constructsText += '\texplicit MTP' + restype + '(MTPD' + name + ' *_data);\n'; # by-data type constructor
constructsInline += 'inline MTP' + restype + '::MTP' + restype + '(MTPD' + name + ' *_data) : mtpDataOwner(_data)';
if (withType): if (withType):
constructsInline += ', _type(mtpc_' + name + ')'; constructsInline += ', _type(mtpc_' + name + ')';
constructsInline += ' {\n}\n'; constructsInline += ' {\n}\n';
@ -654,11 +646,11 @@ for restype in typesList:
readText += '\t\t'; readText += '\t\t';
writeText += '\t\t'; writeText += '\t\t';
if (paramName in conditions): if (paramName in conditions):
readText += '\tif (v.has_' + paramName + '()) { v.v' + paramName + '.read(from, end); } else { v.v' + paramName + ' = MTP' + paramType + '(); }\n'; readText += '\tif (v->has_' + paramName + '()) { v->v' + paramName + '.read(from, end); } else { v->v' + paramName + ' = MTP' + paramType + '(); }\n';
writeText += '\tif (v.has_' + paramName + '()) v.v' + paramName + '.write(to);\n'; writeText += '\tif (v.has_' + paramName + '()) v.v' + paramName + '.write(to);\n';
sizeList.append('(v.has_' + paramName + '() ? v.v' + paramName + '.innerLength() : 0)'); sizeList.append('(v.has_' + paramName + '() ? v.v' + paramName + '.innerLength() : 0)');
else: else:
readText += '\tv.v' + paramName + '.read(from, end);\n'; readText += '\tv->v' + paramName + '.read(from, end);\n';
writeText += '\tv.v' + paramName + '.write(to);\n'; writeText += '\tv.v' + paramName + '.write(to);\n';
sizeList.append('v.v' + paramName + '.innerLength()'); sizeList.append('v.v' + paramName + '.innerLength()');
@ -677,7 +669,7 @@ for restype in typesList:
sizeCases += '\t\t\treturn ' + ' + '.join(sizeList) + ';\n'; sizeCases += '\t\t\treturn ' + ' + '.join(sizeList) + ';\n';
sizeCases += '\t\t}\n'; sizeCases += '\t\t}\n';
sizeFast = '\tconst MTPD' + name + ' &v(c_' + name + '());\n\treturn ' + ' + '.join(sizeList) + ';\n'; sizeFast = '\tconst MTPD' + name + ' &v(c_' + name + '());\n\treturn ' + ' + '.join(sizeList) + ';\n';
newFast = 'new MTPD' + name + '()'; newFast = 'std::make_shared<MTPD' + name + '>()';
else: else:
sizeFast = '\treturn 0;\n'; sizeFast = '\treturn 0;\n';
@ -691,7 +683,7 @@ for restype in typesList:
friendDecl += '\tfriend class MTP::internal::TypeCreator;\n'; friendDecl += '\tfriend class MTP::internal::TypeCreator;\n';
creatorProxyText += '\tinline static MTP' + restype + ' new_' + name + '(' + ', '.join(creatorParams) + ') {\n'; creatorProxyText += '\tinline static MTP' + restype + ' new_' + name + '(' + ', '.join(creatorParams) + ') {\n';
if (len(prms) > len(trivialConditions)): # creator with params if (len(prms) > len(trivialConditions)): # creator with params
creatorProxyText += '\t\treturn MTP' + restype + '(new MTPD' + name + '(' + ', '.join(creatorParamsList) + '));\n'; creatorProxyText += '\t\treturn MTP' + restype + '(std::make_shared<MTPD' + name + '>(' + ', '.join(creatorParamsList) + '));\n';
else: else:
if (withType): # creator by type if (withType): # creator by type
creatorProxyText += '\t\treturn MTP' + restype + '(mtpc_' + name + ');\n'; creatorProxyText += '\t\treturn MTP' + restype + '(mtpc_' + name + ');\n';
@ -708,24 +700,24 @@ for restype in typesList:
reader += '\t\tcase mtpc_' + name + ': _type = cons; '; # read switch line reader += '\t\tcase mtpc_' + name + ': _type = cons; '; # read switch line
if (len(prms) > len(trivialConditions)): if (len(prms) > len(trivialConditions)):
reader += '{\n'; reader += '{\n';
reader += '\t\t\tif (!data) setData(new MTPD' + name + '());\n'; reader += '\t\t\tauto v = std::make_shared<MTPD' + name + '>();\n';
reader += '\t\t\tMTPD' + name + ' &v(_' + name + '());\n';
reader += readText; reader += readText;
reader += '\t\t\tdata = std::move(v);\n';
reader += '\t\t} break;\n'; reader += '\t\t} break;\n';
writer += '\t\tcase mtpc_' + name + ': {\n'; # write switch line writer += '\t\tcase mtpc_' + name + ': {\n'; # write switch line
writer += '\t\t\tconst MTPD' + name + ' &v(c_' + name + '());\n'; writer += '\t\t\tauto &v = c_' + name + '();\n';
writer += writeText; writer += writeText;
writer += '\t\t} break;\n'; writer += '\t\t} break;\n';
else: else:
reader += 'break;\n'; reader += 'break;\n';
else: else:
if (len(prms) > len(trivialConditions)): if (len(prms) > len(trivialConditions)):
reader += '\n\tif (!data) setData(new MTPD' + name + '());\n'; reader += '\n\tauto v = std::make_shared<MTPD' + name + '>();\n';
reader += '\tMTPD' + name + ' &v(_' + name + '());\n';
reader += readText; reader += readText;
reader += '\tdata = std::move(v);\n';
writer += '\tconst MTPD' + name + ' &v(c_' + name + '());\n'; writer += '\tauto &v = c_' + name + '();\n';
writer += writeText; writer += writeText;
forwards += '\n'; forwards += '\n';
@ -739,8 +731,7 @@ for restype in typesList:
inits = []; inits = [];
if (withType): if (withType):
if (withData): if (withData):
inits.append('mtpDataOwner(0)'); inits.append('mtpDataOwner(nullptr)');
inits.append('_type(0)');
else: else:
if (withData): if (withData):
inits.append('mtpDataOwner(' + newFast + ')'); inits.append('mtpDataOwner(' + newFast + ')');
@ -757,9 +748,7 @@ for restype in typesList:
inits = []; inits = [];
if (withData): if (withData):
inits.append('mtpDataOwner(0)'); inits.append('mtpDataOwner(nullptr)');
if (withType):
inits.append('_type(0)');
typesText += '\tMTP' + restype + '(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; typesText += '\tMTP' + restype + '(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons';
if (not withType): if (not withType):
typesText += ' = mtpc_' + name; typesText += ' = mtpc_' + name;
@ -798,7 +787,7 @@ for restype in typesList:
inlineMethods += 'inline void MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n'; inlineMethods += 'inline void MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
if (withData): if (withData):
if (withType): if (withType):
inlineMethods += '\tif (cons != _type) setData(0);\n'; inlineMethods += '\tdata.reset();\n';
else: else:
inlineMethods += '\tif (cons != mtpc_' + v[0][0] + ') throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n'; inlineMethods += '\tif (cons != mtpc_' + v[0][0] + ') throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
if (withType): if (withType):
@ -827,7 +816,7 @@ for restype in typesList:
typesText += '\texplicit MTP' + restype + '(mtpTypeId type);\n'; typesText += '\texplicit MTP' + restype + '(mtpTypeId type);\n';
inlineMethods += 'inline MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : '; inlineMethods += 'inline MTP' + restype + '::MTP' + restype + '(mtpTypeId type) : ';
if (withData): if (withData):
inlineMethods += 'mtpDataOwner(0), '; inlineMethods += 'mtpDataOwner(nullptr), ';
inlineMethods += '_type(type)'; inlineMethods += '_type(type)';
inlineMethods += ' {\n'; inlineMethods += ' {\n';
inlineMethods += '\tswitch (type) {\n'; # type id check inlineMethods += '\tswitch (type) {\n'; # type id check
@ -843,7 +832,7 @@ for restype in typesList:
typesText += '\n' + friendDecl; typesText += '\n' + friendDecl;
if (withType): if (withType):
typesText += '\n\tmtpTypeId _type;\n'; # type field var typesText += '\n\tmtpTypeId _type = 0;\n'; # type field var
typesText += '};\n'; # type class ended typesText += '};\n'; # type class ended

View File

@ -262,7 +262,7 @@ DcId Instance::Private::mainDcId() const {
} }
void Instance::Private::configLoadRequest() { void Instance::Private::configLoadRequest() {
if (_configLoader) { if (_configLoader || true) {
return; return;
} }
_configLoader = std::make_unique<internal::ConfigLoader>(_instance, rpcDone([this](const MTPConfig &result) { _configLoader = std::make_unique<internal::ConfigLoader>(_instance, rpcDone([this](const MTPConfig &result) {

File diff suppressed because it is too large Load Diff

View File

@ -206,13 +206,15 @@ void Session::sendPong(quint64 msgId, quint64 pingId) {
} }
void Session::sendMsgsStateInfo(quint64 msgId, QByteArray data) { void Session::sendMsgsStateInfo(quint64 msgId, QByteArray data) {
MTPMsgsStateInfo req(MTP_msgs_state_info(MTP_long(msgId), MTPstring())); auto info = std::string();
auto &info = req._msgs_state_info().vinfo._string().v;
info.resize(data.size());
if (!data.isEmpty()) { if (!data.isEmpty()) {
memcpy(&info[0], data.constData(), data.size()); info.resize(data.size());
auto src = gsl::as_bytes(gsl::make_span(data));
// auto dst = gsl::as_writeable_bytes(gsl::make_span(info));
auto dst = gsl::as_writeable_bytes(gsl::make_span(&info[0], info.size()));
base::copy_bytes(dst, src);
} }
send(req); send(MTPMsgsStateInfo(MTP_msgs_state_info(MTP_long(msgId), MTP_string(std::move(info)))));
} }
void Session::checkRequestsByTimer() { void Session::checkRequestsByTimer() {

View File

@ -1400,9 +1400,9 @@ EntitiesInText entitiesFromMTP(const QVector<MTPMessageEntity> &entities) {
} }
MTPVector<MTPMessageEntity> linksToMTP(const EntitiesInText &links, bool sending) { MTPVector<MTPMessageEntity> linksToMTP(const EntitiesInText &links, bool sending) {
MTPVector<MTPMessageEntity> result(MTP_vector<MTPMessageEntity>(0)); auto v = QVector<MTPMessageEntity>();
auto &v = result._vector().v; v.reserve(links.size());
for_const (const auto &link, links) { for_const (auto &link, links) {
if (link.length() <= 0) continue; if (link.length() <= 0) continue;
if (sending if (sending
&& link.type() != EntityInTextCode && link.type() != EntityInTextCode
@ -1441,7 +1441,7 @@ MTPVector<MTPMessageEntity> linksToMTP(const EntitiesInText &links, bool sending
case EntityInTextPre: v.push_back(MTP_messageEntityPre(offset, length, MTP_string(link.data()))); break; case EntityInTextPre: v.push_back(MTP_messageEntityPre(offset, length, MTP_string(link.data()))); break;
} }
} }
return result; return MTP_vector<MTPMessageEntity>(std::move(v));
} }
// Some code is duplicated in flattextarea.cpp! // Some code is duplicated in flattextarea.cpp!