Remove exceptions in TL parsing.

This commit is contained in:
John Preston 2019-07-18 16:06:38 +02:00
parent 4a10a88ecf
commit 6aa930d510
18 changed files with 463 additions and 384 deletions

View File

@ -391,19 +391,24 @@ for line in lines:
funcsText += '\tmtpTypeId type() const {\n\t\treturn mtpc_' + name + ';\n\t}\n'; # type id
funcsText += '\tvoid read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ');\n'; # read method
funcsText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_' + name + ');\n'; # read method
if (isTemplate != ''):
methodBodies += 'template <typename TQueryType>\n'
methodBodies += 'void MTP' + name + '<TQueryType>::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
methodBodies += 'bool MTP' + name + '<TQueryType>::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
else:
methodBodies += 'void MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
methodBodies += 'bool MTP' + name + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
readFunc = ''
for k in prmsList:
v = prms[k];
if (k in conditionsList):
if (not k in trivialConditions):
methodBodies += '\tif (_' + hasFlags + '.v & Flag::f_' + k + ') { _' + k + '.read(from, end); } else { _' + k + ' = MTP' + v + '(); }\n';
readFunc += '\t\t&& ((_' + hasFlags + '.v & Flag::f_' + k + ') ? _' + k + '.read(from, end) : ((_' + k + ' = MTP' + v + '()), true))\n';
else:
methodBodies += '\t_' + k + '.read(from, end);\n';
readFunc += '\t\t&& _' + k + '.read(from, end)\n';
if readFunc != '':
methodBodies += '\treturn' + readFunc[4:len(readFunc)-1] + ';\n';
else:
methodBodies += '\treturn true;\n';
methodBodies += '}\n';
funcsText += '\tvoid write(mtpBuffer &to) const;\n'; # write method
@ -485,7 +490,7 @@ def addTextSerialize(lst, dct, dataLetter):
if (isTemplate != ''):
templateArgument = '<MTP::SecureRequest>'
result += 'void Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n';
result += 'bool Serialize_' + name + '(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n';
if (len(conditions)):
result += '\tauto flag = MTP' + dataLetter + name + templateArgument + '::Flags::from_raw(iflag);\n\n';
if (len(prms)):
@ -501,7 +506,7 @@ def addTextSerialize(lst, dct, dataLetter):
v = prms[k];
result += '\tcase ' + str(stage) + ': to.add(" ' + k + ': "); ++stages.back(); ';
if (k == hasFlags):
result += 'if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; ';
result += 'if (start >= end) return false; else flags.back() = *start; ';
if (k in trivialConditions):
result += 'if (flag & MTP' + dataLetter + name + templateArgument + '::Flag::f_' + k + ') { ';
result += 'to.add("YES [ BY BIT ' + conditions[k] + ' IN FIELD ' + hasFlags + ' ]"); ';
@ -564,6 +569,7 @@ def addTextSerialize(lst, dct, dataLetter):
result += '\t}\n';
else:
result += '\tto.add("{ ' + name + ' }"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n';
result += '\treturn true;\n';
result += '}\n\n';
return result;
@ -693,29 +699,30 @@ for restype in typesList:
creatorParams.append('const MTP' + paramType + ' &' + paramName + '_');
creatorParamsList.append(paramName + '_');
prmsInit.append('_' + paramName + '(' + paramName + '_)');
if (withType):
readText += '\t';
writeText += '\t';
if (paramName in conditions):
readText += '\tif (v' + paramName + '()) { _' + paramName + '.read(from, end); } else { _' + paramName + ' = MTP' + paramType + '(); }\n';
readText += '\t\t&& (v' + paramName + '() ? _' + paramName + '.read(from, end) : ((_' + paramName + ' = MTP' + paramType + '()), true))\n';
writeText += '\tif (const auto v' + paramName + ' = v.v' + paramName + '()) v' + paramName + '->write(to);\n';
sizeList.append('(v.v' + paramName + '() ? v.v' + paramName + '()->innerLength() : 0)');
else:
readText += '\t_' + paramName + '.read(from, end);\n';
writeText += '\tv.v' + paramName + '().write(to);\n';
readText += '\t\t&& _' + paramName + '.read(from, end)\n';
writeText += '\t\tv.v' + paramName + '().write(to);\n';
sizeList.append('v.v' + paramName + '().innerLength()');
dataText += ', '.join(prmsStr) + ');\n';
constructsBodies += 'MTPD' + name + '::MTPD' + name + '(' + ', '.join(prmsStr) + ') : ' + ', '.join(prmsInit) + ' {\n}\n';
dataText += '\tMTPD' + name + '(const mtpPrime *&from, const mtpPrime *end);\n'; # reading constructor
dataText += '\n';
dataText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end);\n';
dataText += '\n';
constructsBodies += 'MTPD' + name + '::MTPD' + name + '(const mtpPrime *&from, const mtpPrime *end) {\n';
constructsBodies += readText;
constructsBodies += 'bool MTPD' + name + '::read(const mtpPrime *&from, const mtpPrime *end) {\n';
if readText != '':
constructsBodies += '\treturn' + readText[4:len(readText)-1] + ';\n';
else:
constructsBodies += '\treturn true;\n';
constructsBodies += '}\n';
dataText += '\n';
if len(prmsList) > 0:
for paramName in prmsList: # getters
if (paramName in trivialConditions):
@ -780,7 +787,12 @@ for restype in typesList:
reader += '\tcase mtpc_' + name + ': _type = cons; '; # read switch line
if (len(prms) > len(trivialConditions)):
reader += '{\n';
reader += '\t\tsetData(new MTPD' + name + '(from, end));\n';
reader += '\t\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n';
reader += '\t\t\tsetData(data);\n';
reader += '\t\t} else {\n';
reader += '\t\t\tdelete data;\n';
reader += '\t\t\treturn false;\n';
reader += '\t\t}\n';
reader += '\t} break;\n';
writer += '\tcase mtpc_' + name + ': {\n'; # write switch line
@ -791,7 +803,12 @@ for restype in typesList:
reader += 'break;\n';
else:
if (len(prms) > len(trivialConditions)):
reader += '\tsetData(new MTPD' + name + '(from, end));\n';
reader += '\tif (const auto data = new MTPD' + name + '(); data->read(from, end)) {\n';
reader += '\t\tsetData(data);\n';
reader += '\t} else {\n';
reader += '\t\tdelete data;\n';
reader += '\t\treturn false;\n';
reader += '\t}\n';
writer += '\tconst MTPD' + name + ' &v = c_' + name + '();\n';
writer += writeText;
@ -844,21 +861,22 @@ for restype in typesList:
methods += '\treturn mtpc_' + v[0][0] + ';\n';
methods += '}\n';
typesText += '\tvoid read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; # read method
typesText += '\t[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons'; # read method
if (not withType):
typesText += ' = mtpc_' + name;
typesText += ');\n';
methods += 'void MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
methods += 'bool MTP' + restype + '::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {\n';
if (withData):
if not (withType):
methods += '\tif (cons != mtpc_' + v[0][0] + ') throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\tif (cons != mtpc_' + v[0][0] + ') return false;\n';
if (withType):
methods += '\tswitch (cons) {\n'
methods += reader;
methods += '\tdefault: throw mtpErrorUnexpected(cons, "MTP' + restype + '");\n';
methods += '\tdefault: return false;\n';
methods += '\t}\n';
else:
methods += reader;
methods += '\treturn true;\n';
methods += '}\n';
typesText += '\tvoid write(mtpBuffer &to) const;\n'; # write method
@ -881,7 +899,8 @@ for restype in typesList:
methods += ' {\n';
methods += '\tswitch (type) {\n'; # type id check
methods += switchLines;
methods += '\tdefault: throw mtpErrorBadTypeId(type, "MTP' + restype + '");\n\t}\n';
methods += '\tdefault: Unexpected("Type in MTP' + restype + '::MTP' + restype + '.");\n';
methods += '\t}\n';
methods += '}\n'; # by-type-id constructor end
if (withData):
@ -925,7 +944,7 @@ for childName in parentFlagsList:
# manual types added here
textSerializeMethods += '\
void _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
bool _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
if (stage) {\n\
to.add(",\\n").addSpaces(lev);\n\
} else {\n\
@ -937,9 +956,10 @@ void _serialize_rpc_result(MTPStringLogger &to, int32 stage, int32 lev, Types &t
case 1: to.add(" result: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\
}\n\
return true;\n\
}\n\
\n\
void _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
bool _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
if (stage) {\n\
to.add(",\\n").addSpaces(lev);\n\
} else {\n\
@ -950,9 +970,10 @@ void _serialize_msg_container(MTPStringLogger &to, int32 stage, int32 lev, Types
case 0: to.add(" messages: "); ++stages.back(); types.push_back(mtpc_vector); vtypes.push_back(mtpc_core_message); stages.push_back(0); flags.push_back(0); break;\n\
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\
}\n\
return true;\n\
}\n\
\n\
void _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
bool _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag) {\n\
if (stage) {\n\
to.add(",\\n").addSpaces(lev);\n\
} else {\n\
@ -966,6 +987,7 @@ void _serialize_core_message(MTPStringLogger &to, int32 stage, int32 lev, Types
case 3: to.add(" body: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;\n\
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;\n\
}\n\
return true;\n\
}\n\
\n';
@ -1027,7 +1049,7 @@ enum {\n\
// Factory methods declaration\n\
' + factories + '\n\
// Human-readable text serialization\n\
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n'
[[nodiscard]] bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons);\n'
source = '\
/*\n\
@ -1063,20 +1085,19 @@ using StagesFlags = QVector<int32>;\n\
' + textSerializeMethods + '\n\
namespace {\n\
\n\
using TextSerializer = void (*)(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag);\n\
using TextSerializer = bool (*)(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, uint32 iflag);\n\
using TextSerializers = QMap<mtpTypeId, TextSerializer>;\n\
\n\
QMap<mtpTypeId, TextSerializer> createTextSerializers() {\n\
auto result = QMap<mtpTypeId, TextSerializer>();\n\
\n\
' + textSerializeInit + '\n\
\n\
return result;\n\
}\n\
\n\
} // namespace\n\
\n\
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons) {\n\
bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons, uint32 level, mtpPrime vcons) {\n\
static auto serializers = createTextSerializers();\n\
\n\
QVector<mtpTypeId> types, vtypes;\n\
@ -1094,9 +1115,11 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
flag = flags.back();\n\
if (!type) {\n\
if (from >= end) {\n\
throw Exception("from >= end");\n\
to.error("insufficient data");\n\
return false;\n\
} else if (stage) {\n\
throw Exception("unknown type on stage > 0");\n\
to.error("unknown type on stage > 0");\n\
return false;\n\
}\n\
types.back() = type = *from;\n\
++from;\n\
@ -1105,12 +1128,18 @@ void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpP
int32 lev = level + types.size() - 1;\n\
auto it = serializers.constFind(type);\n\
if (it != serializers.cend()) {\n\
(*it.value())(to, stage, lev, types, vtypes, stages, flags, from, end, flag);\n\
} else {\n\
mtpTextSerializeCore(to, from, end, type, lev, vtype);\n\
if (!(*it.value())(to, stage, lev, types, vtypes, stages, flags, from, end, flag)) {\n\
to.error();\n\
return false;\n\
}\n\
} else if (mtpTextSerializeCore(to, from, end, type, lev, vtype)) {\n\
types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back();\n\
} else {\n\
to.error();\n\
return false;\n\
}\n\
}\n\
return true;\n\
}\n';
already_header = ''

View File

@ -780,8 +780,9 @@ void Application::authSessionCreate(const MTPUser &user) {
const mtpPrime *from,
const mtpPrime *end) {
if (const auto main = App::main()) {
main->updateReceived(from, end);
return main->updateReceived(from, end);
}
return true;
}));
_mtproto->setGlobalFailHandler(::rpcFail([=](const RPCError &error) {
if (activeAccount().sessionExists()) {

View File

@ -3666,35 +3666,35 @@ void MainWidget::checkIdleFinish() {
}
}
void MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
if (end <= from) return;
bool MainWidget::updateReceived(const mtpPrime *from, const mtpPrime *end) {
if (end <= from) {
return false;
}
session().checkAutoLock();
if (mtpTypeId(*from) == mtpc_new_session_created) {
try {
MTPNewSession newSession;
newSession.read(from, end);
} catch (mtpErrorUnexpected &) {
MTPNewSession newSession;
if (!newSession.read(from, end)) {
return false;
}
updSeq = 0;
MTP_LOG(0, ("getDifference { after new_session_created }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
} else {
try {
MTPUpdates updates;
updates.read(from, end);
_lastUpdateTime = crl::now();
_noUpdatesTimer.callOnce(kNoUpdatesTimeout);
if (!requestingDifference()
|| HasForceLogoutNotification(updates)) {
feedUpdates(updates);
}
} catch (mtpErrorUnexpected &) { // just some other type
}
getDifference();
return true;
}
update();
MTPUpdates updates;
if (!updates.read(from, end)) {
return false;
}
_lastUpdateTime = crl::now();
_noUpdatesTimer.callOnce(kNoUpdatesTimeout);
if (!requestingDifference()
|| HasForceLogoutNotification(updates)) {
feedUpdates(updates);
}
return true;
}
void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) {

View File

@ -121,7 +121,7 @@ public:
void incrementSticker(DocumentData *sticker);
void activate();
void updateReceived(const mtpPrime *from, const mtpPrime *end);
[[nodiscard]] bool updateReceived(const mtpPrime *from, const mtpPrime *end);
void refreshDialog(Dialogs::Key key);
void removeDialog(Dialogs::Key key);

View File

@ -18,7 +18,7 @@ public:
not_null<ConcurrentSender*> sender,
Fn<void(FnMut<void()>)> runner);
void operator()(
bool operator()(
mtpRequestId requestId,
const mtpPrime *from,
const mtpPrime *end) override;
@ -54,7 +54,7 @@ ConcurrentSender::RPCDoneHandler::RPCDoneHandler(
, _runner(std::move(runner)) {
}
void ConcurrentSender::RPCDoneHandler::operator()(
bool ConcurrentSender::RPCDoneHandler::operator()(
mtpRequestId requestId,
const mtpPrime *from,
const mtpPrime *end) {
@ -66,6 +66,7 @@ void ConcurrentSender::RPCDoneHandler::operator()(
strong->senderRequestDone(requestId, std::move(moved));
}
});
return true;
}
ConcurrentSender::RPCFailHandler::RPCFailHandler(
@ -178,14 +179,12 @@ void ConcurrentSender::senderRequestDone(
mtpRequestId requestId,
bytes::const_span result) {
if (auto handlers = _requests.take(requestId)) {
try {
handlers->done(requestId, result);
} catch (Exception &e) {
if (!handlers->done(requestId, result)) {
handlers->fail(
requestId,
RPCError::Local(
"RESPONSE_PARSE_FAILED",
QString("exception text: ") + e.what()));
"ConcurrentSender::senderRequestDone"));
}
}
}

View File

@ -32,7 +32,7 @@ class ConcurrentSender : public base::has_weak_ptr {
auto with_instance(Method &&method)
-> std::enable_if_t<is_callable_v<Method, not_null<Instance*>>>;
using DoneHandler = FnMut<void(
using DoneHandler = FnMut<bool(
mtpRequestId requestId,
bytes::const_span result)>;
using FailHandler = FnMut<void(
@ -206,8 +206,11 @@ void ConcurrentSender::RequestBuilder::setDoneHandler(
auto from = reinterpret_cast<const mtpPrime*>(result.data());
const auto end = from + result.size() / sizeof(mtpPrime);
Response data;
data.read(from, end);
if (!data.read(from, end)) {
return false;
}
std::move(handler)(requestId, std::move(data));
return true;
};
}

View File

@ -1637,8 +1637,7 @@ void ConnectionPrivate::handleReceived() {
}
ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime) {
mtpTypeId cons = *from;
try {
const auto cons = *from;
switch (cons) {
@ -1652,17 +1651,23 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
}
case mtpc_msg_container: {
if (++from >= end) throw mtpErrorInsufficient();
if (++from >= end) {
return HandleResult::ParseError;
}
const mtpPrime *otherEnd;
uint32 msgsCount = (uint32)*(from++);
const auto msgsCount = (uint32)*(from++);
DEBUG_LOG(("Message Info: container received, count: %1").arg(msgsCount));
for (uint32 i = 0; i < msgsCount; ++i) {
if (from + 4 >= end) throw mtpErrorInsufficient();
if (from + 4 >= end) {
return HandleResult::ParseError;
}
otherEnd = from + 4;
MTPlong inMsgId;
inMsgId.read(from, otherEnd);
if (!inMsgId.read(from, otherEnd)) {
return HandleResult::ParseError;
}
bool isReply = ((inMsgId.v & 0x03) == 1);
if (!isReply && ((inMsgId.v & 0x03) != 3)) {
LOG(("Message Error: bad msg_id %1 in contained message received").arg(inMsgId.v));
@ -1670,9 +1675,13 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
}
MTPint inSeqNo;
inSeqNo.read(from, otherEnd);
if (!inSeqNo.read(from, otherEnd)) {
return HandleResult::ParseError;
}
MTPint bytes;
bytes.read(from, otherEnd);
if (!bytes.read(from, otherEnd)) {
return HandleResult::ParseError;
}
if ((bytes.v & 0x03) || bytes.v < 4) {
LOG(("Message Error: bad length %1 of contained message received").arg(bytes.v));
return HandleResult::RestartConnection;
@ -1684,7 +1693,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
DEBUG_LOG(("Message Info: message from container, msg_id: %1, needAck: %2").arg(inMsgId.v).arg(Logs::b(needAck)));
otherEnd = from + (bytes.v >> 2);
if (otherEnd > end) throw mtpErrorInsufficient();
if (otherEnd > end) {
return HandleResult::ParseError;
}
bool needToHandle = false;
{
@ -1706,7 +1717,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_msgs_ack: {
MTPMsgsAck msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
auto &ids = msg.c_msgs_ack().vmsg_ids().v;
uint32 idsCount = ids.size();
@ -1725,7 +1738,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_bad_msg_notification: {
MTPBadMsgNotification msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_bad_msg_notification());
LOG(("Message Info: bad message notification received (error_code %3) for msg_id = %1, seq_no = %2").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.verror_code().v));
@ -1822,7 +1837,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_bad_server_salt: {
MTPBadMsgNotification msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_bad_server_salt());
DEBUG_LOG(("Message Info: bad server salt received (error_code %4) for msg_id = %1, seq_no = %2, new salt: %3").arg(data.vbad_msg_id().v).arg(data.vbad_msg_seqno().v).arg(data.vnew_server_salt().v).arg(data.verror_code().v));
@ -1857,7 +1874,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
return HandleResult::Ignored;
}
MTPMsgsStateReq msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
auto &ids = msg.c_msgs_state_req().vmsg_ids().v;
auto idsCount = ids.size();
DEBUG_LOG(("Message Info: msgs_state_req received, ids: %1").arg(LogIdsVector(ids)));
@ -1905,7 +1924,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_msgs_state_info: {
MTPMsgsStateInfo msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
auto &data = msg.c_msgs_state_info();
auto reqMsgId = data.vreq_msg_id().v;
@ -1938,20 +1959,21 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
LOG(("Message Error: bad request %1 found in requestMap, size: %2").arg(reqMsgId).arg(requestBuffer->size()));
return HandleResult::RestartConnection;
}
try {
const mtpPrime *rFrom = requestBuffer->constData() + 8, *rEnd = requestBuffer->constData() + requestBuffer->size();
if (mtpTypeId(*rFrom) == mtpc_msgs_state_req) {
MTPMsgsStateReq request;
request.read(rFrom, rEnd);
handleMsgsStates(request.c_msgs_state_req().vmsg_ids().v, states, toAck);
} else {
MTPMsgResendReq request;
request.read(rFrom, rEnd);
handleMsgsStates(request.c_msg_resend_req().vmsg_ids().v, states, toAck);
const mtpPrime *rFrom = requestBuffer->constData() + 8, *rEnd = requestBuffer->constData() + requestBuffer->size();
if (mtpTypeId(*rFrom) == mtpc_msgs_state_req) {
MTPMsgsStateReq request;
if (!request.read(rFrom, rEnd)) {
LOG(("Message Error: could not parse sent msgs_state_req"));
return HandleResult::ParseError;
}
} catch(Exception &) {
LOG(("Message Error: could not parse sent msgs_state_req"));
throw;
handleMsgsStates(request.c_msgs_state_req().vmsg_ids().v, states, toAck);
} else {
MTPMsgResendReq request;
if (!request.read(rFrom, rEnd)) {
LOG(("Message Error: could not parse sent msgs_state_req"));
return HandleResult::ParseError;
}
handleMsgsStates(request.c_msg_resend_req().vmsg_ids().v, states, toAck);
}
requestsAcked(toAck);
@ -1964,7 +1986,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
}
MTPMsgsAllInfo msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
auto &data = msg.c_msgs_all_info();
auto &ids = data.vmsg_ids().v;
auto &states = data.vinfo().v;
@ -1979,7 +2003,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_msg_detailed_info: {
MTPMsgDetailedInfo msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_msg_detailed_info());
DEBUG_LOG(("Message Info: msg detailed info, sent msgId %1, answerId %2, status %3, bytes %4").arg(data.vmsg_id().v).arg(data.vanswer_msg_id().v).arg(data.vstatus().v).arg(data.vbytes().v));
@ -2015,7 +2041,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
return HandleResult::Ignored;
}
MTPMsgDetailedInfo msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_msg_new_detailed_info());
DEBUG_LOG(("Message Info: msg new detailed info, answerId %2, status %3, bytes %4").arg(data.vanswer_msg_id().v).arg(data.vstatus().v).arg(data.vbytes().v));
@ -2036,7 +2064,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_msg_resend_req: {
MTPMsgResendReq msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
auto &ids = msg.c_msg_resend_req().vmsg_ids().v;
auto idsCount = ids.size();
@ -2051,11 +2081,15 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
} return HandleResult::Success;
case mtpc_rpc_result: {
if (from + 3 > end) throw mtpErrorInsufficient();
if (from + 3 > end) {
return HandleResult::ParseError;
}
auto response = SerializedMessage();
MTPlong reqMsgId;
reqMsgId.read(++from, end);
if (!reqMsgId.read(++from, end)) {
return HandleResult::ParseError;
}
mtpTypeId typeId = from[0];
DEBUG_LOG(("RPC Info: response received for %1, queueing...").arg(reqMsgId.v));
@ -2074,7 +2108,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
if (typeId == mtpc_gzip_packed) {
DEBUG_LOG(("RPC Info: gzip container"));
response = ungzip(++from, end);
if (!response.size()) {
if (response.empty()) {
return HandleResult::RestartConnection;
}
typeId = response[0];
@ -2105,7 +2139,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_new_session_created: {
const mtpPrime *start = from;
MTPNewSession msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_new_session_created());
if (badTime) {
@ -2143,7 +2179,9 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
case mtpc_pong: {
MTPPong msg;
msg.read(from, end);
if (!msg.read(from, end)) {
return HandleResult::ParseError;
}
const auto &data(msg.c_pong());
DEBUG_LOG(("Message Info: pong received, msg_id: %1, ping_id: %2").arg(data.vmsg_id().v).arg(data.vping_id().v));
@ -2170,10 +2208,6 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
}
} catch (Exception &) {
return HandleResult::RestartConnection;
}
if (badTime) {
DEBUG_LOG(("Message Error: bad time in updates cons, must create new session"));
return HandleResult::ResetSession;
@ -2205,12 +2239,16 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
}
mtpBuffer ConnectionPrivate::ungzip(const mtpPrime *from, const mtpPrime *end) const {
MTPstring packed;
packed.read(from, end); // read packed string as serialized mtp string type
uint32 packedLen = packed.v.size(), unpackedChunk = packedLen, unpackedLen = 0;
mtpBuffer result; // * 4 because of mtpPrime type
result.resize(0);
MTPstring packed;
if (!packed.read(from, end)) { // read packed string as serialized mtp string type
LOG(("RPC Error: could not read gziped bytes."));
return result;
}
uint32 packedLen = packed.v.size(), unpackedChunk = packedLen, unpackedLen = 0;
z_stream stream;
stream.zalloc = 0;
stream.zfree = 0;
@ -2730,7 +2768,10 @@ void ConnectionPrivate::dhParamsAnswered() {
const mtpPrime *from(&decBuffer[5]), *to(from), *end(from + (encDHBufLen - 5));
MTPServer_DH_inner_data dh_inner;
dh_inner.read(to, end);
if (!dh_inner.read(to, end)) {
LOG(("AuthKey Error: could not decrypt server_DH_inner_data!"));
return restart();
}
const auto &dh_inner_data(dh_inner.c_server_DH_inner_data());
if (dh_inner_data.vnonce() != _authKeyData->nonce) {
LOG(("AuthKey Error: received nonce <> sent nonce (in server_DH_inner_data)!"));
@ -3100,13 +3141,8 @@ bool ConnectionPrivate::readNotSecureResponse(Response &response) {
if (answer.empty()) {
return false;
}
try {
auto from = answer.data();
response.read(from, from + answer.size());
} catch (Exception &) {
return false;
}
return true;
auto from = answer.data();
return response.read(from, from + answer.size());
}
bool ConnectionPrivate::sendSecureRequest(

View File

@ -195,8 +195,9 @@ private:
Ignored,
RestartConnection,
ResetSession,
ParseError,
};
HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime);
[[nodiscard]] HandleResult handleOneReceived(const mtpPrime *from, const mtpPrime *end, uint64 msgId, int32 serverTime, uint64 serverSalt, bool badTime);
mtpBuffer ungzip(const mtpPrime *from, const mtpPrime *end) const;
void handleMsgsStates(const QVector<MTPlong> &ids, const QByteArray &states, QVector<MTPlong> &acked);
@ -225,7 +226,7 @@ private:
void sendNotSecureRequest(const Request &request);
template <typename Response>
bool readNotSecureResponse(Response &response);
[[nodiscard]] bool readNotSecureResponse(Response &response);
not_null<Instance*> _instance;
DcType _dcType = DcType::Regular;

View File

@ -141,16 +141,17 @@ mtpBuffer AbstractConnection::preparePQFake(const MTPint128 &nonce) const {
base::unixtime::mtproto_msg_id());
}
MTPResPQ AbstractConnection::readPQFakeReply(
std::optional<MTPResPQ> AbstractConnection::readPQFakeReply(
const mtpBuffer &buffer) const {
const auto answer = parseNotSecureResponse(buffer);
if (answer.empty()) {
throw Exception("bad pq reply");
return std::nullopt;
}
auto from = answer.data();
MTPResPQ response;
response.read(from, from + answer.size());
return response;
return response.read(from, from + answer.size())
? std::make_optional(response)
: std::nullopt;
}
AbstractConnection::AbstractConnection(

View File

@ -137,7 +137,7 @@ protected:
// first we always send fake MTPReq_pq to see if connection works at all
// we send them simultaneously through TCP/HTTP/IPv4/IPv6 to choose the working one
mtpBuffer preparePQFake(const MTPint128 &nonce) const;
MTPResPQ readPQFakeReply(const mtpBuffer &buffer) const;
std::optional<MTPResPQ> readPQFakeReply(const mtpBuffer &buffer) const;
};

View File

@ -167,28 +167,24 @@ void HttpConnection::requestFinished(QNetworkReply *reply) {
if (_status == Status::Ready) {
_receivedQueue.push_back(data);
emit receivedData();
} else {
try {
const auto res_pq = readPQFakeReply(data);
const auto &data = res_pq.c_resPQ();
if (data.vnonce() == _checkNonce) {
DEBUG_LOG(("Connection Info: "
"HTTP-transport to %1 connected by pq-response"
).arg(_address));
_status = Status::Ready;
_pingTime = crl::now() - _pingTime;
emit connected();
} else {
DEBUG_LOG(("Connection Error: "
"Wrong nonce received in HTTP fake pq-responce"));
emit error(kErrorCodeOther);
}
} catch (Exception &e) {
} else if (const auto res_pq = readPQFakeReply(data)) {
const auto &data = res_pq->c_resPQ();
if (data.vnonce() == _checkNonce) {
DEBUG_LOG(("Connection Info: "
"HTTP-transport to %1 connected by pq-response"
).arg(_address));
_status = Status::Ready;
_pingTime = crl::now() - _pingTime;
emit connected();
} else {
DEBUG_LOG(("Connection Error: "
"Exception in parsing HTTP fake pq-responce, %1"
).arg(e.what()));
"Wrong nonce received in HTTP fake pq-responce"));
emit error(kErrorCodeOther);
}
} else {
DEBUG_LOG(("Connection Error: "
"Could not parse HTTP fake pq-responce"));
emit error(kErrorCodeOther);
}
}
} else {

View File

@ -615,9 +615,8 @@ void TcpConnection::socketPacket(bytes::const_span bytes) {
_receivedQueue.push_back(data);
emit receivedData();
} else if (_status == Status::Waiting) {
try {
const auto res_pq = readPQFakeReply(data);
const auto &data = res_pq.c_resPQ();
if (const auto res_pq = readPQFakeReply(data)) {
const auto &data = res_pq->c_resPQ();
if (data.vnonce() == _checkNonce) {
DEBUG_LOG(("Connection Info: Valid pq response by TCP."));
_status = Status::Ready;
@ -629,10 +628,9 @@ void TcpConnection::socketPacket(bytes::const_span bytes) {
"Wrong nonce received in TCP fake pq-responce"));
emit error(kErrorCodeOther);
}
} catch (Exception &e) {
} else {
DEBUG_LOG(("Connection Error: "
"Exception in parsing TCP fake pq-responce, %1"
).arg(e.what()));
"Could not parse TCP fake pq-responce"));
emit error(kErrorCodeOther);
}
}

View File

@ -147,36 +147,6 @@ bool SecureRequest::needAck() const {
} // namespace MTP
Exception::Exception(const QString &msg) noexcept : _msg(msg.toUtf8()) {
LOG(("Exception: %1").arg(msg));
}
mtpErrorUnexpected::mtpErrorUnexpected(
mtpTypeId typeId,
const QString &type) noexcept
: Exception(
QString("MTP Unexpected type id #%1 read in %2"
).arg(uint32(typeId), 0, 16
).arg(type)) {
}
mtpErrorInsufficient::mtpErrorInsufficient() noexcept
: Exception("MTP Insufficient bytes in input buffer") {
}
mtpErrorBadTypeId::mtpErrorBadTypeId(
mtpTypeId typeId,
const QString &type) noexcept
: Exception(
QString("MTP Bad type id #%1 passed to constructor of %2"
).arg(uint32(typeId), 0, 16
).arg(type)) {
}
const char *Exception::what() const noexcept {
return _msg.constData();
}
uint32 MTPstring::innerLength() const {
uint32 l = v.length();
if (l < 254) {
@ -189,9 +159,10 @@ uint32 MTPstring::innerLength() const {
return l;
}
void MTPstring::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_string) throw mtpErrorUnexpected(cons, "MTPstring");
bool MTPstring::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons) {
if (from + 1 > end || cons != mtpc_string) {
return false;
}
uint32 l;
const uchar *buf = (const uchar*)from;
@ -204,9 +175,12 @@ void MTPstring::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons)
++buf;
from += ((l + 1) >> 2) + (((l + 1) & 0x03) ? 1 : 0);
}
if (from > end) throw mtpErrorInsufficient();
if (from > end) {
return false;
}
v = QByteArray(reinterpret_cast<const char*>(buf), l);
return true;
}
void MTPstring::write(mtpBuffer &to) const {
@ -229,74 +203,91 @@ void MTPstring::write(mtpBuffer &to) const {
memcpy(buf, v.constData(), l);
}
void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) {
bool mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) {
switch (mtpTypeId(cons)) {
case mtpc_int: {
MTPint value;
value.read(from, end, cons);
to.add(QString::number(value.v)).add(" [INT]");
if (value.read(from, end, cons)) {
to.add(QString::number(value.v)).add(" [INT]");
return true;
}
} break;
case mtpc_long: {
MTPlong value;
value.read(from, end, cons);
to.add(QString::number(value.v)).add(" [LONG]");
if (value.read(from, end, cons)) {
to.add(QString::number(value.v)).add(" [LONG]");
return true;
}
} break;
case mtpc_int128: {
MTPint128 value;
value.read(from, end, cons);
to.add(QString::number(value.h)).add(" * 2^64 + ").add(QString::number(value.l)).add(" [INT128]");
if (value.read(from, end, cons)) {
to.add(QString::number(value.h)).add(" * 2^64 + ").add(QString::number(value.l)).add(" [INT128]");
return true;
}
} break;
case mtpc_int256: {
MTPint256 value;
value.read(from, end, cons);
to.add(QString::number(value.h.h)).add(" * 2^192 + ").add(QString::number(value.h.l)).add(" * 2^128 + ").add(QString::number(value.l.h)).add(" * 2 ^ 64 + ").add(QString::number(value.l.l)).add(" [INT256]");
if (value.read(from, end, cons)) {
to.add(QString::number(value.h.h)).add(" * 2^192 + ").add(QString::number(value.h.l)).add(" * 2^128 + ").add(QString::number(value.l.h)).add(" * 2 ^ 64 + ").add(QString::number(value.l.l)).add(" [INT256]");
return true;
}
} break;
case mtpc_double: {
MTPdouble value;
value.read(from, end, cons);
to.add(QString::number(value.v)).add(" [DOUBLE]");
if (value.read(from, end, cons)) {
to.add(QString::number(value.v)).add(" [DOUBLE]");
return true;
}
} break;
case mtpc_string: {
MTPstring value;
value.read(from, end, cons);
auto strUtf8 = value.v;
auto str = QString::fromUtf8(strUtf8);
if (str.toUtf8() == strUtf8) {
to.add("\"").add(str.replace('\\', "\\\\").replace('"', "\\\"").replace('\n', "\\n")).add("\" [STRING]");
} else if (strUtf8.size() < 64) {
to.add(Logs::mb(strUtf8.constData(), strUtf8.size()).str()).add(" [").add(QString::number(strUtf8.size())).add(" BYTES]");
} else {
to.add(Logs::mb(strUtf8.constData(), 16).str()).add("... [").add(QString::number(strUtf8.size())).add(" BYTES]");
if (value.read(from, end, cons)) {
auto strUtf8 = value.v;
auto str = QString::fromUtf8(strUtf8);
if (str.toUtf8() == strUtf8) {
to.add("\"").add(str.replace('\\', "\\\\").replace('"', "\\\"").replace('\n', "\\n")).add("\" [STRING]");
} else if (strUtf8.size() < 64) {
to.add(Logs::mb(strUtf8.constData(), strUtf8.size()).str()).add(" [").add(QString::number(strUtf8.size())).add(" BYTES]");
} else {
to.add(Logs::mb(strUtf8.constData(), 16).str()).add("... [").add(QString::number(strUtf8.size())).add(" BYTES]");
}
return true;
}
} break;
case mtpc_vector: {
if (from >= end) {
throw Exception("from >= end in vector");
}
int32 cnt = *(from++);
to.add("[ vector<0x").add(QString::number(vcons, 16)).add(">");
if (cnt) {
to.add("\n").addSpaces(level);
for (int32 i = 0; i < cnt; ++i) {
to.add(" ");
mtpTextSerializeType(to, from, end, vcons, level + 1);
to.add(",\n").addSpaces(level);
if (from < end) {
int32 cnt = *(from++);
to.add("[ vector<0x").add(QString::number(vcons, 16)).add(">");
if (cnt) {
to.add("\n").addSpaces(level);
for (int32 i = 0; i < cnt; ++i) {
to.add(" ");
if (!mtpTextSerializeType(to, from, end, vcons, level + 1)) {
return false;
}
to.add(",\n").addSpaces(level);
}
} else {
to.add(" ");
}
} else {
to.add(" ");
to.add("]");
return true;
}
to.add("]");
} break;
case mtpc_gzip_packed: {
MTPstring packed;
packed.read(from, end); // read packed string as serialized mtp string type
// read packed string as serialized mtp string type
if (!packed.read(from, end)) {
return false;
}
uint32 packedLen = packed.v.size(), unpackedChunk = packedLen;
mtpBuffer result; // * 4 because of mtpPrime type
result.resize(0);
@ -309,7 +300,7 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
stream.next_in = nullptr;
int res = inflateInit2(&stream, 16 + MAX_WBITS);
if (res != Z_OK) {
throw Exception(QString("ungzip init, code: %1").arg(res));
return false;
}
stream.avail_in = packedLen;
stream.next_in = reinterpret_cast<Bytef*>(packed.v.data());
@ -321,39 +312,39 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
int res = inflate(&stream, Z_NO_FLUSH);
if (res != Z_OK && res != Z_STREAM_END) {
inflateEnd(&stream);
throw Exception(QString("ungzip unpack, code: %1").arg(res));
return false;
}
}
if (stream.avail_out & 0x03) {
uint32 badSize = result.size() * sizeof(mtpPrime) - stream.avail_out;
throw Exception(QString("ungzip bad length, size: %1").arg(badSize));
return false;
}
result.resize(result.size() - (stream.avail_out >> 2));
inflateEnd(&stream);
if (result.empty()) {
throw Exception("ungzip void data");
return false;
}
const mtpPrime *newFrom = result.constData(), *newEnd = result.constData() + result.size();
to.add("[GZIPPED] "); mtpTextSerializeType(to, newFrom, newEnd, 0, level);
to.add("[GZIPPED] ");
return mtpTextSerializeType(to, newFrom, newEnd, 0, level);
} break;
default: {
for (uint32 i = 1; i < mtpLayerMaxSingle; ++i) {
if (cons == mtpLayers[i]) {
to.add("[LAYER").add(QString::number(i + 1)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
return;
to.add("[LAYER").add(QString::number(i + 1)).add("] ");
return mtpTextSerializeType(to, from, end, 0, level);
}
}
if (cons == mtpc_invokeWithLayer) {
if (from >= end) {
throw Exception("from >= end in invokeWithLayer");
return false;
}
int32 layer = *(from++);
to.add("[LAYER").add(QString::number(layer)).add("] "); mtpTextSerializeType(to, from, end, 0, level);
return;
to.add("[LAYER").add(QString::number(layer)).add("] ");
return mtpTextSerializeType(to, from, end, 0, level);
}
throw Exception(QString("unknown cons 0x%1").arg(cons, 0, 16));
} break;
}
return false;
}

View File

@ -59,35 +59,6 @@ constexpr int GetDcIdShift(ShiftedDcId shiftedDcId) {
} // namespace MTP
class Exception : public std::exception {
public:
explicit Exception(const QString &msg) noexcept;
const char *what() const noexcept override;
private:
QByteArray _msg;
};
class mtpErrorUnexpected : public Exception {
public:
mtpErrorUnexpected(mtpTypeId typeId, const QString &type) noexcept;
};
class mtpErrorInsufficient : public Exception {
public:
mtpErrorInsufficient() noexcept;
};
class mtpErrorBadTypeId : public Exception {
public:
mtpErrorBadTypeId(mtpTypeId typeId, const QString &type) noexcept;
};
namespace MTP {
namespace internal {
@ -259,10 +230,12 @@ public:
uint32 innerLength() const {
return sizeof(mtpTypeId) + bareT::innerLength();
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) {
if (from + 1 > end) throw mtpErrorInsufficient();
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) {
if (from + 1 > end) {
return false;
}
cons = (mtpTypeId)*(from++);
bareT::read(from, end, cons);
return bareT::read(from, end, cons);
}
void write(mtpBuffer &to) const {
to.push_back(bareT::type());
@ -439,10 +412,12 @@ public:
mtpTypeId type() const {
return mtpc_int;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_int) throw mtpErrorUnexpected(cons, "MTPint");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int) {
if (from + 1 > end || cons != mtpc_int) {
return false;
}
v = (int32)*(from++);
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)v);
@ -477,10 +452,12 @@ public:
mtpTypeId type() const {
return mtpc_flags;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_flags) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_flags) throw mtpErrorUnexpected(cons, "MTPflags");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_flags) {
if (from + 1 > end || cons != mtpc_flags) {
return false;
}
v = Flags::from_raw(static_cast<typename Flags::Type>(*(from++)));
return true;
}
void write(mtpBuffer &to) const {
to.push_back(static_cast<mtpPrime>(v.value()));
@ -534,11 +511,13 @@ public:
mtpTypeId type() const {
return mtpc_long;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_long) {
if (from + 2 > end) throw mtpErrorInsufficient();
if (cons != mtpc_long) throw mtpErrorUnexpected(cons, "MTPlong");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_long) {
if (from + 2 > end || cons != mtpc_long) {
return false;
}
v = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
from += 2;
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)(v & 0xFFFFFFFFL));
@ -576,12 +555,14 @@ public:
mtpTypeId type() const {
return mtpc_int128;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int128) {
if (from + 4 > end) throw mtpErrorInsufficient();
if (cons != mtpc_int128) throw mtpErrorUnexpected(cons, "MTPint128");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int128) {
if (from + 4 > end || cons != mtpc_int128) {
return false;
}
l = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
h = (uint64)(((uint32*)from)[2]) | ((uint64)(((uint32*)from)[3]) << 32);
from += 4;
return true;
}
void write(mtpBuffer &to) const {
to.push_back((mtpPrime)(l & 0xFFFFFFFFL));
@ -621,10 +602,12 @@ public:
mtpTypeId type() const {
return mtpc_int256;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int256) {
if (cons != mtpc_int256) throw mtpErrorUnexpected(cons, "MTPint256");
l.read(from, end);
h.read(from, end);
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_int256) {
if (cons != mtpc_int256) {
return false;
}
return l.read(from, end)
&& h.read(from, end);
}
void write(mtpBuffer &to) const {
l.write(to);
@ -661,12 +644,14 @@ public:
mtpTypeId type() const {
return mtpc_double;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_double) {
if (from + 2 > end) throw mtpErrorInsufficient();
if (cons != mtpc_double) throw mtpErrorUnexpected(cons, "MTPdouble");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_double) {
if (from + 2 > end || cons != mtpc_double) {
return false;
}
auto nv = (uint64)(((uint32*)from)[0]) | ((uint64)(((uint32*)from)[1]) << 32);
std::memcpy(&v, &nv, sizeof(v));
from += 2;
return true;
}
void write(mtpBuffer &to) const {
uint64 iv;
@ -704,7 +689,7 @@ public:
mtpTypeId type() const {
return mtpc_string;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string);
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_string);
void write(mtpBuffer &to) const;
QByteArray v;
@ -792,16 +777,20 @@ public:
mtpTypeId type() const {
return mtpc_vector;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_vector) {
if (from + 1 > end) throw mtpErrorInsufficient();
if (cons != mtpc_vector) throw mtpErrorUnexpected(cons, "MTPvector");
[[nodiscard]] bool read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_vector) {
if (from + 1 > end || cons != mtpc_vector) {
return false;
}
auto count = static_cast<uint32>(*(from++));
auto vector = QVector<T>(count, T());
for (auto &item : vector) {
item.read(from, end);
if (!item.read(from, end)) {
return false;
}
}
v = std::move(vector);
return true;
}
void write(mtpBuffer &to) const {
to.push_back(v.size());
@ -900,6 +889,10 @@ struct MTPStringLogger {
return (*this);
}
MTPStringLogger &error(const char *problem = "could not decode type") {
return add("[ERROR] (").add(problem).add(")");
}
void ensureLength(int32 add) {
if (size + add <= alloced) return;
@ -920,16 +913,12 @@ struct MTPStringLogger {
};
void mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons = 0, uint32 level = 0, mtpPrime vcons = 0);
[[nodiscard]] bool mtpTextSerializeType(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpPrime cons = 0, uint32 level = 0, mtpPrime vcons = 0);
void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons = 0);
[[nodiscard]] bool mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons = 0);
inline QString mtpTextSerialize(const mtpPrime *&from, const mtpPrime *end) {
MTPStringLogger to;
try {
mtpTextSerializeType(to, from, end, mtpc_core_message);
} catch (Exception &e) {
to.add("[ERROR] (").add(e.what()).add(")");
}
[[maybe_unused]] bool result = mtpTextSerializeType(to, from, end, mtpc_core_message);
return QString::fromUtf8(to.p, to.size);
}

View File

@ -1064,22 +1064,24 @@ void Instance::Private::execCallback(
}
};
try {
if (from >= end) throw mtpErrorInsufficient();
if (*from == mtpc_rpc_error) {
auto error = MTPRpcError();
error.read(from, end);
handleError(error);
} else {
if (h.onDone) {
(*h.onDone)(requestId, from, end);
}
unregisterRequest(requestId);
}
} catch (Exception &e) {
if (from >= end) {
handleError(RPCError::Local(
"RESPONSE_PARSE_FAILED",
QString("exception text: ") + e.what()));
"Empty response."));
} else if (*from == mtpc_rpc_error) {
auto error = MTPRpcError();
handleError(error.read(from, end) ? error : RPCError::Local(
"RESPONSE_PARSE_FAILED",
"Error parse failed."));
} else {
if (h.onDone) {
if (!(*h.onDone)(requestId, from, end)) {
handleError(RPCError::Local(
"RESPONSE_PARSE_FAILED",
"Response parse failed."));
}
}
unregisterRequest(requestId);
}
} else {
DEBUG_LOG(("RPC Info: parser not found for %1").arg(requestId));

View File

@ -67,7 +67,7 @@ inline bool isDefaultHandledError(const RPCError &error) {
class RPCAbstractDoneHandler { // abstract done
public:
virtual void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) = 0;
virtual [[nodiscard]] bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) = 0;
virtual ~RPCAbstractDoneHandler() {
}
@ -94,15 +94,14 @@ struct RPCResponseHandler {
};
template <typename TReturn>
class RPCDoneHandlerBare : public RPCAbstractDoneHandler { // done(from, end)
using CallbackType = TReturn (*)(const mtpPrime *, const mtpPrime *);
using CallbackType = bool (*)(const mtpPrime *, const mtpPrime *);
public:
RPCDoneHandlerBare(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
(*_onDone)(from, end);
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return (*_onDone)(from, end);
}
private:
@ -110,15 +109,14 @@ private:
};
template <typename TReturn>
class RPCDoneHandlerBareReq : public RPCAbstractDoneHandler { // done(from, end, req_id)
using CallbackType = TReturn (*)(const mtpPrime *, const mtpPrime *, mtpRequestId);
using CallbackType = bool (*)(const mtpPrime *, const mtpPrime *, mtpRequestId);
public:
RPCDoneHandlerBareReq(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
(*_onDone)(from, end, requestId);
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return (*_onDone)(from, end, requestId);
}
private:
@ -133,10 +131,13 @@ class RPCDoneHandlerPlain : public RPCAbstractDoneHandler { // done(result)
public:
RPCDoneHandlerPlain(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
response.read(from, end);
if (!response.read(from, end)) {
return false;
}
(*_onDone)(std::move(response));
return true;
}
private:
@ -151,10 +152,13 @@ class RPCDoneHandlerReq : public RPCAbstractDoneHandler { // done(result, req_id
public:
RPCDoneHandlerReq(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
response.read(from, end);
if (!response.read(from, end)) {
return false;
}
(*_onDone)(std::move(response), requestId);
return true;
}
private:
@ -169,8 +173,9 @@ class RPCDoneHandlerNo : public RPCAbstractDoneHandler { // done()
public:
RPCDoneHandlerNo(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
(*_onDone)();
return true;
}
private:
@ -185,8 +190,9 @@ class RPCDoneHandlerNoReq : public RPCAbstractDoneHandler { // done(req_id)
public:
RPCDoneHandlerNoReq(CallbackType onDone) : _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
(*_onDone)(requestId);
return true;
}
private:
@ -265,14 +271,12 @@ struct RPCCallbackClear {
};
template <typename TReturn>
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)(const mtpPrime *, const mtpPrime *)) { // done(from, end)
return RPCDoneHandlerPtr(new RPCDoneHandlerBare<TReturn>(onDone));
inline RPCDoneHandlerPtr rpcDone(bool (*onDone)(const mtpPrime *, const mtpPrime *)) { // done(from, end)
return RPCDoneHandlerPtr(new RPCDoneHandlerBare(onDone));
}
template <typename TReturn>
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)(const mtpPrime *, const mtpPrime *, mtpRequestId)) { // done(from, end, req_id)
return RPCDoneHandlerPtr(new RPCDoneHandlerBareReq<TReturn>(onDone));
inline RPCDoneHandlerPtr rpcDone(bool (*onDone)(const mtpPrime *, const mtpPrime *, mtpRequestId)) { // done(from, end, req_id)
return RPCDoneHandlerPtr(new RPCDoneHandlerBareReq(onDone));
}
template <typename TReturn, typename TResponse>
@ -346,7 +350,7 @@ class RPCDoneHandlerBareOwned : public RPCOwnedDoneHandler { // done(from, end)
public:
RPCDoneHandlerBareOwned(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(from, end);
}
@ -355,15 +359,17 @@ private:
};
template <typename TReturn, typename TReceiver>
template <typename TReceiver>
class RPCDoneHandlerBareOwnedReq : public RPCOwnedDoneHandler { // done(from, end, req_id)
using CallbackType = TReturn (TReceiver::*)(const mtpPrime *, const mtpPrime *, mtpRequestId);
using CallbackType = bool (TReceiver::*)(const mtpPrime *, const mtpPrime *, mtpRequestId);
public:
RPCDoneHandlerBareOwnedReq(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(from, end, requestId);
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return _owner
? (static_cast<TReceiver*>(_owner)->*_onDone)(from, end, requestId)
: true;
}
private:
@ -378,12 +384,15 @@ class RPCDoneHandlerOwned : public RPCOwnedDoneHandler { // done(result)
public:
RPCDoneHandlerOwned(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (_owner) {
auto response = TResponse();
response.read(from, end);
(static_cast<TReceiver*>(_owner)->*_onDone)(std::move(response));
}
return true;
}
private:
@ -398,12 +407,15 @@ class RPCDoneHandlerOwnedReq : public RPCOwnedDoneHandler { // done(result, req_
public:
RPCDoneHandlerOwnedReq(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (_owner) {
auto response = TResponse();
response.read(from, end);
(static_cast<TReceiver*>(_owner)->*_onDone)(std::move(response), requestId);
}
return true;
}
private:
@ -418,8 +430,9 @@ class RPCDoneHandlerOwnedNo : public RPCOwnedDoneHandler { // done()
public:
RPCDoneHandlerOwnedNo(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)();
return true;
}
private:
@ -434,8 +447,9 @@ class RPCDoneHandlerOwnedNoReq : public RPCOwnedDoneHandler { // done(req_id)
public:
RPCDoneHandlerOwnedNoReq(TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(requestId);
return true;
}
private:
@ -443,15 +457,17 @@ private:
};
template <typename T, typename TReturn, typename TReceiver>
template <typename T, typename TReceiver>
class RPCBindedDoneHandlerBareOwned : public RPCOwnedDoneHandler { // done(b, from, end)
using CallbackType = TReturn (TReceiver::*)(T, const mtpPrime *, const mtpPrime *);
using CallbackType = bool (TReceiver::*)(T, const mtpPrime *, const mtpPrime *);
public:
RPCBindedDoneHandlerBareOwned(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _b(b), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(_b, from, end);
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return _owner
? (static_cast<TReceiver*>(_owner)->*_onDone)(_b, from, end)
: true;
}
private:
@ -462,13 +478,15 @@ private:
template <typename T, typename TReturn, typename TReceiver>
class RPCBindedDoneHandlerBareOwnedReq : public RPCOwnedDoneHandler { // done(b, from, end, req_id)
using CallbackType = TReturn (TReceiver::*)(T, const mtpPrime *, const mtpPrime *, mtpRequestId);
using CallbackType = bool (TReceiver::*)(T, const mtpPrime *, const mtpPrime *, mtpRequestId);
public:
RPCBindedDoneHandlerBareOwnedReq(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _b(b), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(_b, from, end, requestId);
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return _owner
? (static_cast<TReceiver*>(_owner)->*_onDone)(_b, from, end, requestId)
: true;
}
private:
@ -484,12 +502,15 @@ class RPCBindedDoneHandlerOwned : public RPCOwnedDoneHandler { // done(b, result
public:
RPCBindedDoneHandlerOwned(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone), _b(b) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (_owner) {
auto response = TResponse();
response.read(from, end);
(static_cast<TReceiver*>(_owner)->*_onDone)(_b, std::move(response));
}
return true;
}
private:
@ -505,12 +526,15 @@ class RPCBindedDoneHandlerOwnedReq : public RPCOwnedDoneHandler { // done(b, res
public:
RPCBindedDoneHandlerOwnedReq(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _onDone(onDone), _b(b) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (_owner) {
auto response = TResponse();
response.read(from, end);
(static_cast<TReceiver*>(_owner)->*_onDone)(_b, std::move(response), requestId);
}
return true;
}
private:
@ -526,8 +550,9 @@ class RPCBindedDoneHandlerOwnedNo : public RPCOwnedDoneHandler { // done(b)
public:
RPCBindedDoneHandlerOwnedNo(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _b(b), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(_b);
return true;
}
private:
@ -543,8 +568,9 @@ class RPCBindedDoneHandlerOwnedNoReq : public RPCOwnedDoneHandler { // done(b, r
public:
RPCBindedDoneHandlerOwnedNoReq(T b, TReceiver *receiver, CallbackType onDone) : RPCOwnedDoneHandler(receiver), _b(b), _onDone(onDone) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (_owner) (static_cast<TReceiver*>(_owner)->*_onDone)(_b, requestId);
return true;
}
private:
@ -851,22 +877,20 @@ protected:
template <typename FunctionType>
using RPCDoneHandlerImplementation = RPCHandlerImplementation<RPCAbstractDoneHandler, FunctionType>;
template <typename R>
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)> { // done(from, end)
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*)> { // done(from, end)
public:
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return this->_handler ? this->_handler(from, end) : void(0);
using RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*)>::Parent::Parent;
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return this->_handler ? this->_handler(from, end) : true;
}
};
template <typename R>
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
public:
using RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return this->_handler ? this->_handler(from, end, requestId) : void(0);
using RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*, mtpRequestId)>::Parent::Parent;
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
return this->_handler ? this->_handler(from, end, requestId) : true;
}
};
@ -875,12 +899,15 @@ template <typename R, typename TResponse>
class RPCDoneHandlerImplementationPlain : public RPCDoneHandlerImplementation<R(const TResponse&)> { // done(result)
public:
using RPCDoneHandlerImplementation<R(const TResponse&)>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (this->_handler) {
auto response = TResponse();
response.read(from, end);
this->_handler(std::move(response));
}
return true;
}
};
@ -889,12 +916,15 @@ template <typename R, typename TResponse>
class RPCDoneHandlerImplementationReq : public RPCDoneHandlerImplementation<R(const TResponse&, mtpRequestId)> { // done(result, req_id)
public:
using RPCDoneHandlerImplementation<R(const TResponse&, mtpRequestId)>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto response = TResponse();
if (!response.read(from, end)) {
return false;
}
if (this->_handler) {
auto response = TResponse();
response.read(from, end);
this->_handler(std::move(response), requestId);
}
return true;
}
};
@ -903,10 +933,11 @@ template <typename R>
class RPCDoneHandlerImplementationNo : public RPCDoneHandlerImplementation<R()> { // done()
public:
using RPCDoneHandlerImplementation<R()>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (this->_handler) {
this->_handler();
}
return true;
}
};
@ -915,10 +946,11 @@ template <typename R>
class RPCDoneHandlerImplementationNoReq : public RPCDoneHandlerImplementation<R(mtpRequestId)> { // done(req_id)
public:
using RPCDoneHandlerImplementation<R(mtpRequestId)>::Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
if (this->_handler) {
this->_handler(requestId);
}
return true;
}
};
@ -995,9 +1027,9 @@ template <
RPCDoneHandlerPtr rpcDone(Lambda lambda) {
using R = rpcDone_returnType_t<Function>;
if constexpr (rpcDone_canCallBare_v<Lambda>) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare<R>(std::move(lambda)));
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare(std::move(lambda)));
} else if constexpr (rpcDone_canCallBareReq_v<Lambda>) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq<R>(std::move(lambda)));
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq(std::move(lambda)));
} else if constexpr (rpcDone_canCallNo_v<Lambda>) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNo<R>(std::move(lambda)));
} else if constexpr (rpcDone_canCallNoReq_v<Lambda>) {

View File

@ -54,15 +54,18 @@ class Sender {
DoneHandler(not_null<Sender*> sender, Callback handler) : _sender(sender), _handler(std::move(handler)) {
}
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
auto handler = std::move(_handler);
_sender->senderRequestHandled(requestId);
auto result = Response();
if (!result.read(from, end)) {
return false;
}
if (handler) {
auto result = Response();
result.read(from, end);
Policy::handle(std::move(handler), requestId, std::move(result));
}
return true;
}
private:

View File

@ -458,9 +458,7 @@ bool SpecialConfigRequest::decryptSimpleConfig(const QByteArray &bytes) {
return false;
}
try {
_simpleConfig.read(from, end);
} catch (...) {
if (!_simpleConfig.read(from, end)) {
LOG(("Config Error: Could not read configSimple."));
return false;
}