mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Handle new paddings in improved TCP protocol.
This commit is contained in:
parent
22441ef80c
commit
941288b58e
@ -1415,7 +1415,7 @@ void ConnectionPrivate::handleReceived() {
|
||||
}
|
||||
|
||||
auto encryptedInts = ints + kExternalHeaderIntsCount;
|
||||
auto encryptedIntsCount = (intsCount - kExternalHeaderIntsCount);
|
||||
auto encryptedIntsCount = (intsCount - kExternalHeaderIntsCount) & ~0x03U;
|
||||
auto encryptedBytesCount = encryptedIntsCount * kIntSize;
|
||||
auto decryptedBuffer = QByteArray(encryptedBytesCount, Qt::Uninitialized);
|
||||
auto msgKey = *(MTPint128*)(ints + 2);
|
||||
@ -3062,35 +3062,22 @@ template <typename Response>
|
||||
bool ConnectionPrivate::readNotSecureResponse(Response &response) {
|
||||
onReceivedSome();
|
||||
|
||||
if (_connection->received().empty()) {
|
||||
LOG(("AuthKey Error: "
|
||||
"trying to read response from empty received list"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto buffer = std::move(_connection->received().front());
|
||||
_connection->received().pop_front();
|
||||
|
||||
const auto answer = _connection->parseNotSecureResponse(buffer);
|
||||
if (answer.empty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (_connection->received().empty()) {
|
||||
LOG(("AuthKey Error: trying to read response from empty received list"));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto buffer = std::move(_connection->received().front());
|
||||
_connection->received().pop_front();
|
||||
|
||||
auto answer = buffer.constData();
|
||||
auto len = buffer.size();
|
||||
if (len < 5) {
|
||||
LOG(("AuthKey Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return false;
|
||||
}
|
||||
if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet
|
||||
LOG(("AuthKey Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2]));
|
||||
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return false;
|
||||
}
|
||||
uint32 answerLen = (uint32)answer[4];
|
||||
if (answerLen != (len - 5) * sizeof(mtpPrime)) {
|
||||
LOG(("AuthKey Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return false;
|
||||
}
|
||||
const mtpPrime *from(answer + 5), *end(from + len - 5);
|
||||
response.read(from, end);
|
||||
auto from = answer.data();
|
||||
response.read(from, from + answer.size());
|
||||
} catch (Exception &) {
|
||||
return false;
|
||||
}
|
||||
|
@ -97,33 +97,56 @@ mtpBuffer AbstractConnection::prepareSecurePacket(
|
||||
return result;
|
||||
}
|
||||
|
||||
gsl::span<const mtpPrime> AbstractConnection::parseNotSecureResponse(
|
||||
const mtpBuffer &buffer) const {
|
||||
const auto answer = buffer.data();
|
||||
const auto len = buffer.size();
|
||||
if (len < 6) {
|
||||
LOG(("Not Secure Error: bad request answer, len = %1"
|
||||
).arg(len * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("Not Secure Error: answer bytes %1"
|
||||
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return {};
|
||||
}
|
||||
if (answer[0] != 0
|
||||
|| answer[1] != 0
|
||||
|| (((uint32)answer[2]) & 0x03) != 1
|
||||
//|| (unixtime() - answer[3] > 300) // We didn't sync time yet.
|
||||
//|| (answer[3] - unixtime() > 60)
|
||||
|| false) {
|
||||
LOG(("Not Secure Error: bad request answer start (%1 %2 %3)"
|
||||
).arg(answer[0]
|
||||
).arg(answer[1]
|
||||
).arg(answer[2]));
|
||||
DEBUG_LOG(("Not Secure Error: answer bytes %1"
|
||||
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return {};
|
||||
}
|
||||
const auto answerLen = (uint32)answer[4];
|
||||
if (answerLen < 1 || answerLen > (len - 5) * sizeof(mtpPrime)) {
|
||||
LOG(("Not Secure Error: bad request answer 1 <= %1 <= %2"
|
||||
).arg(answerLen
|
||||
).arg((len - 5) * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("Not Secure Error: answer bytes %1"
|
||||
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
return {};
|
||||
}
|
||||
return gsl::make_span(answer + 5, answerLen);
|
||||
}
|
||||
|
||||
mtpBuffer AbstractConnection::preparePQFake(const MTPint128 &nonce) const {
|
||||
return prepareNotSecurePacket(MTPReq_pq(nonce));
|
||||
}
|
||||
|
||||
MTPResPQ AbstractConnection::readPQFakeReply(
|
||||
const mtpBuffer &buffer) const {
|
||||
const mtpPrime *answer(buffer.constData());
|
||||
uint32 len = buffer.size();
|
||||
if (len < 5) {
|
||||
LOG(("Fake PQ Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
const auto answer = parseNotSecureResponse(buffer);
|
||||
if (answer.empty()) {
|
||||
throw Exception("bad pq reply");
|
||||
}
|
||||
if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet
|
||||
LOG(("Fake PQ Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2]));
|
||||
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
throw Exception("bad pq reply");
|
||||
}
|
||||
uint32 answerLen = (uint32)answer[4];
|
||||
if (answerLen != (len - 5) * sizeof(mtpPrime)) {
|
||||
LOG(("Fake PQ Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime)));
|
||||
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
|
||||
throw Exception("bad pq reply");
|
||||
}
|
||||
const mtpPrime *from(answer + 5), *end(from + len - 5);
|
||||
auto from = answer.data();
|
||||
MTPResPQ response;
|
||||
response.read(from, end);
|
||||
response.read(from, from + answer.size());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,9 @@ public:
|
||||
MTPint128 msgKey,
|
||||
uint32 size) const;
|
||||
|
||||
gsl::span<const mtpPrime> parseNotSecureResponse(
|
||||
const mtpBuffer &buffer) const;
|
||||
|
||||
// Used to emit error(...) with no real code from the server.
|
||||
static constexpr auto kErrorCodeOther = -499;
|
||||
|
||||
|
@ -169,16 +169,24 @@ void HttpConnection::requestFinished(QNetworkReply *reply) {
|
||||
emit receivedData();
|
||||
} else {
|
||||
try {
|
||||
auto res_pq = readPQFakeReply(data);
|
||||
const auto &res_pq_data(res_pq.c_resPQ());
|
||||
if (res_pq_data.vnonce == _checkNonce) {
|
||||
DEBUG_LOG(("Connection Info: HTTP-transport to %1 connected by pq-response").arg(_address));
|
||||
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 = getms() - _pingTime;
|
||||
emit connected();
|
||||
} else {
|
||||
DEBUG_LOG(("Connection Error: "
|
||||
"Wrong nonce received in HTTP fake pq-responce"));
|
||||
emit error(kErrorCodeOther);
|
||||
}
|
||||
} catch (Exception &e) {
|
||||
DEBUG_LOG(("Connection Error: exception in parsing HTTP fake pq-responce, %1").arg(e.what()));
|
||||
DEBUG_LOG(("Connection Error: "
|
||||
"Exception in parsing HTTP fake pq-responce, %1"
|
||||
).arg(e.what()));
|
||||
emit error(kErrorCodeOther);
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,9 @@ namespace MTP {
|
||||
namespace internal {
|
||||
namespace {
|
||||
|
||||
constexpr auto kPacketSizeMax = 64 * 1024 * 1024U;
|
||||
constexpr auto kPacketSizeMax = 0x01000000 * sizeof(mtpPrime);
|
||||
constexpr auto kFullConnectionTimeout = 8 * TimeMs(1000);
|
||||
|
||||
uint32 CountTcpPacketSize(const char *packet) { // must have at least 4 bytes readable
|
||||
uint32 result = (packet[0] > 0) ? packet[0] : 0;
|
||||
if (result == 0x7f) {
|
||||
const uchar *bytes = reinterpret_cast<const uchar*>(packet);
|
||||
result = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]);
|
||||
return (result << 2) + 4;
|
||||
}
|
||||
return (result << 2) + 1;
|
||||
}
|
||||
|
||||
using ErrorSignal = void(QTcpSocket::*)(QAbstractSocket::SocketError);
|
||||
const auto QTcpSocket_error = ErrorSignal(&QAbstractSocket::error);
|
||||
|
||||
@ -42,11 +32,17 @@ public:
|
||||
static std::unique_ptr<Protocol> Create(bytes::vector &&secret);
|
||||
|
||||
virtual uint32 id() const = 0;
|
||||
virtual bool requiresExtendedPadding() const = 0;
|
||||
virtual bool supportsArbitraryLength() const = 0;
|
||||
|
||||
virtual bool requiresExtendedPadding() const = 0;
|
||||
virtual void prepareKey(bytes::span key, bytes::const_span source) = 0;
|
||||
virtual bytes::span finalizePacket(mtpBuffer &buffer) = 0;
|
||||
|
||||
static constexpr auto kUnknownSize = uint32(-1);
|
||||
static constexpr auto kInvalidSize = uint32(-2);
|
||||
virtual uint32 readPacketLength(bytes::const_span bytes) const = 0;
|
||||
virtual bytes::const_span readPacket(bytes::const_span bytes) const = 0;
|
||||
|
||||
virtual ~Protocol() = default;
|
||||
|
||||
private:
|
||||
@ -59,22 +55,26 @@ private:
|
||||
class TcpConnection::Protocol::Version0 : public Protocol {
|
||||
public:
|
||||
uint32 id() const override;
|
||||
bool requiresExtendedPadding() const override;
|
||||
bool supportsArbitraryLength() const override;
|
||||
|
||||
bool requiresExtendedPadding() const override;
|
||||
void prepareKey(bytes::span key, bytes::const_span source) override;
|
||||
bytes::span finalizePacket(mtpBuffer &buffer) override;
|
||||
|
||||
uint32 readPacketLength(bytes::const_span bytes) const override;
|
||||
bytes::const_span readPacket(bytes::const_span bytes) const override;
|
||||
|
||||
};
|
||||
|
||||
uint32 TcpConnection::Protocol::Version0::id() const {
|
||||
return 0xEFEFEFEFU;
|
||||
}
|
||||
|
||||
bool TcpConnection::Protocol::Version0::requiresExtendedPadding() const {
|
||||
bool TcpConnection::Protocol::Version0::supportsArbitraryLength() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TcpConnection::Protocol::Version0::supportsArbitraryLength() const {
|
||||
bool TcpConnection::Protocol::Version0::requiresExtendedPadding() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -105,6 +105,37 @@ bytes::span TcpConnection::Protocol::Version0::finalizePacket(
|
||||
return bytes::make_span(buffer).subspan(8 - added, added + bytesSize);
|
||||
}
|
||||
|
||||
uint32 TcpConnection::Protocol::Version0::readPacketLength(
|
||||
bytes::const_span bytes) const {
|
||||
if (bytes.empty()) {
|
||||
return kUnknownSize;
|
||||
}
|
||||
const auto first = static_cast<char>(bytes[0]);
|
||||
if (first == 0x7F) {
|
||||
if (bytes.size() < 4) {
|
||||
return kUnknownSize;
|
||||
}
|
||||
const auto ints = static_cast<uint32>(bytes[1])
|
||||
| (static_cast<uint32>(bytes[2]) << 8)
|
||||
| (static_cast<uint32>(bytes[3]) << 16);
|
||||
return (ints >= 0x7F) ? ((ints << 2) + 4) : kInvalidSize;
|
||||
} else if (first > 0 && first < 0x7F) {
|
||||
const auto ints = uint32(first);
|
||||
return (ints << 2) + 1;
|
||||
}
|
||||
return kInvalidSize;
|
||||
}
|
||||
|
||||
bytes::const_span TcpConnection::Protocol::Version0::readPacket(
|
||||
bytes::const_span bytes) const {
|
||||
const auto size = readPacketLength(bytes);
|
||||
Assert(size != kUnknownSize
|
||||
&& size != kInvalidSize
|
||||
&& size <= bytes.size());
|
||||
const auto sizeLength = (static_cast<char>(bytes[0]) == 0x7F) ? 4 : 1;
|
||||
return bytes.subspan(sizeLength, size - sizeLength);
|
||||
}
|
||||
|
||||
class TcpConnection::Protocol::Version1 : public Version0 {
|
||||
public:
|
||||
explicit Version1(bytes::vector &&secret);
|
||||
@ -138,8 +169,12 @@ public:
|
||||
|
||||
uint32 id() const override;
|
||||
bool supportsArbitraryLength() const override;
|
||||
|
||||
bytes::span finalizePacket(mtpBuffer &buffer) override;
|
||||
|
||||
uint32 readPacketLength(bytes::const_span bytes) const override;
|
||||
bytes::const_span readPacket(bytes::const_span bytes) const override;
|
||||
|
||||
};
|
||||
|
||||
uint32 TcpConnection::Protocol::VersionD::id() const {
|
||||
@ -165,6 +200,25 @@ bytes::span TcpConnection::Protocol::VersionD::finalizePacket(
|
||||
return bytes::make_span(buffer).subspan(4, 4 + bytesSize);
|
||||
}
|
||||
|
||||
uint32 TcpConnection::Protocol::VersionD::readPacketLength(
|
||||
bytes::const_span bytes) const {
|
||||
if (bytes.size() < 4) {
|
||||
return kUnknownSize;
|
||||
}
|
||||
const auto value = *reinterpret_cast<const uint32*>(bytes.data()) + 4;
|
||||
return (value >= 8 && value < kPacketSizeMax) ? value : kInvalidSize;
|
||||
}
|
||||
|
||||
bytes::const_span TcpConnection::Protocol::VersionD::readPacket(
|
||||
bytes::const_span bytes) const {
|
||||
const auto size = readPacketLength(bytes);
|
||||
Assert(size != kUnknownSize
|
||||
&& size != kInvalidSize
|
||||
&& size <= bytes.size());
|
||||
const auto sizeLength = 4;
|
||||
return bytes.subspan(sizeLength, size - sizeLength);
|
||||
}
|
||||
|
||||
auto TcpConnection::Protocol::Create(bytes::vector &&secret)
|
||||
-> std::unique_ptr<Protocol> {
|
||||
if (secret.size() == 17 && static_cast<uchar>(secret[0]) == 0xDD) {
|
||||
@ -251,26 +305,36 @@ void TcpConnection::socketRead() {
|
||||
if (_packetLeft) {
|
||||
_packetLeft -= bytes;
|
||||
if (!_packetLeft) {
|
||||
socketPacket(_currentPosition - _packetRead, _packetRead);
|
||||
socketPacket(bytes::make_span(
|
||||
_currentPosition - _packetRead,
|
||||
_packetRead));
|
||||
_currentPosition = (char*)_shortBuffer;
|
||||
_packetRead = _packetLeft = 0;
|
||||
_readingToShort = true;
|
||||
_longBuffer.clear();
|
||||
} else {
|
||||
TCP_LOG(("TCP Info: not enough %1 for packet! read %2").arg(_packetLeft).arg(_packetRead));
|
||||
TCP_LOG(("TCP Info: not enough %1 for packet! read %2"
|
||||
).arg(_packetLeft
|
||||
).arg(_packetRead));
|
||||
emit receivedSome();
|
||||
}
|
||||
} else {
|
||||
bool move = false;
|
||||
while (_packetRead >= 4) {
|
||||
uint32 packetSize = CountTcpPacketSize(_currentPosition - _packetRead);
|
||||
if (packetSize < 5 || packetSize > kPacketSizeMax) {
|
||||
const auto packetSize = _protocol->readPacketLength(
|
||||
bytes::make_span(
|
||||
_currentPosition - _packetRead,
|
||||
_packetRead));
|
||||
if (packetSize == Protocol::kUnknownSize
|
||||
|| packetSize == Protocol::kInvalidSize) {
|
||||
LOG(("TCP Error: packet size = %1").arg(packetSize));
|
||||
emit error(kErrorCodeOther);
|
||||
return;
|
||||
}
|
||||
if (_packetRead >= packetSize) {
|
||||
socketPacket(_currentPosition - _packetRead, packetSize);
|
||||
socketPacket(bytes::make_span(
|
||||
_currentPosition - _packetRead,
|
||||
packetSize));
|
||||
_packetRead -= packetSize;
|
||||
_packetLeft = 0;
|
||||
move = true;
|
||||
@ -305,39 +369,30 @@ void TcpConnection::socketRead() {
|
||||
} while (_socket.state() == QAbstractSocket::ConnectedState && _socket.bytesAvailable());
|
||||
}
|
||||
|
||||
mtpBuffer TcpConnection::handleResponse(const char *packet, uint32 length) {
|
||||
if (length < 5 || length > kPacketSizeMax) {
|
||||
LOG(("TCP Error: bad packet size %1").arg(length));
|
||||
return mtpBuffer(1, -500);
|
||||
mtpBuffer TcpConnection::parsePacket(bytes::const_span bytes) {
|
||||
const auto packet = _protocol->readPacket(bytes);
|
||||
TCP_LOG(("TCP Info: packet received, size = %1"
|
||||
).arg(packet.size()));
|
||||
const auto ints = gsl::make_span(
|
||||
reinterpret_cast<const mtpPrime*>(packet.data()),
|
||||
packet.size() / sizeof(mtpPrime));
|
||||
Assert(!ints.empty());
|
||||
if (ints.size() < 3) {
|
||||
// nop or error or new quickack, latter is not yet supported.
|
||||
if (ints[0] != 0) {
|
||||
LOG(("TCP Error: "
|
||||
"error packet received, endpoint: '%1:%2', "
|
||||
"protocolDcId: %3, code = %4"
|
||||
).arg(_address.isEmpty() ? ("prx_" + _proxy.host) : _address
|
||||
).arg(_address.isEmpty() ? _proxy.port : _port
|
||||
).arg(_protocolDcId
|
||||
).arg(ints[0]));
|
||||
}
|
||||
return mtpBuffer(1, ints[0]);
|
||||
}
|
||||
int32 size = packet[0], len = length - 1;
|
||||
if (size == 0x7f) {
|
||||
const uchar *bytes = reinterpret_cast<const uchar*>(packet);
|
||||
size = (((uint32(bytes[3]) << 8) | uint32(bytes[2])) << 8) | uint32(bytes[1]);
|
||||
len -= 3;
|
||||
}
|
||||
if (size * int32(sizeof(mtpPrime)) != len) {
|
||||
LOG(("TCP Error: bad packet header"));
|
||||
TCP_LOG(("TCP Error: bad packet header, packet: %1").arg(Logs::mb(packet, length).str()));
|
||||
return mtpBuffer(1, -500);
|
||||
}
|
||||
const mtpPrime *packetdata = reinterpret_cast<const mtpPrime*>(packet + (length - len));
|
||||
TCP_LOG(("TCP Info: packet received, size = %1").arg(size * sizeof(mtpPrime)));
|
||||
if (size == 1) {
|
||||
LOG(("TCP Error: "
|
||||
"error packet received, endpoint: '%1:%2', "
|
||||
"protocolDcId: %3, code = %4"
|
||||
).arg(_address.isEmpty() ? ("proxy_" + _proxy.host) : _address
|
||||
).arg(_address.isEmpty() ? _proxy.port : _port
|
||||
).arg(_protocolDcId
|
||||
).arg(*packetdata));
|
||||
return mtpBuffer(1, *packetdata);
|
||||
}
|
||||
|
||||
mtpBuffer data(size);
|
||||
memcpy(data.data(), packetdata, size * sizeof(mtpPrime));
|
||||
|
||||
return data;
|
||||
auto result = mtpBuffer(ints.size());
|
||||
memcpy(result.data(), ints.data(), ints.size() * sizeof(mtpPrime));
|
||||
return result;
|
||||
}
|
||||
|
||||
void TcpConnection::handleError(QAbstractSocket::SocketError e, QTcpSocket &socket) {
|
||||
@ -541,12 +596,19 @@ TimeMs TcpConnection::fullConnectTimeout() const {
|
||||
return kFullConnectionTimeout;
|
||||
}
|
||||
|
||||
void TcpConnection::socketPacket(const char *packet, uint32 length) {
|
||||
void TcpConnection::socketPacket(bytes::const_span bytes) {
|
||||
if (_status == Status::Finished) return;
|
||||
|
||||
const auto data = handleResponse(packet, length);
|
||||
// old quickack?..
|
||||
const auto data = parsePacket(bytes);
|
||||
if (data.size() == 1) {
|
||||
emit error(data[0]);
|
||||
if (data[0] != 0) {
|
||||
emit error(data[0]);
|
||||
} else {
|
||||
// nop
|
||||
}
|
||||
//} else if (data.size() == 2) {
|
||||
// new quickack?..
|
||||
} else if (_status == Status::Ready) {
|
||||
_receivedQueue.push_back(data);
|
||||
emit receivedData();
|
||||
@ -564,9 +626,15 @@ void TcpConnection::socketPacket(const char *packet, uint32 length) {
|
||||
nullptr);
|
||||
_pingTime = (getms() - _pingTime);
|
||||
emit connected();
|
||||
} else {
|
||||
DEBUG_LOG(("Connection Error: "
|
||||
"Wrong nonce received in TCP fake pq-responce"));
|
||||
emit error(kErrorCodeOther);
|
||||
}
|
||||
} catch (Exception &e) {
|
||||
DEBUG_LOG(("Connection Error: exception in parsing TCP fake pq-responce, %1").arg(e.what()));
|
||||
DEBUG_LOG(("Connection Error: "
|
||||
"Exception in parsing TCP fake pq-responce, %1"
|
||||
).arg(e.what()));
|
||||
emit error(kErrorCodeOther);
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ private:
|
||||
void socketRead();
|
||||
void writeConnectionStart();
|
||||
|
||||
void socketPacket(const char *packet, uint32 length);
|
||||
void socketPacket(bytes::const_span bytes);
|
||||
|
||||
void socketConnected();
|
||||
void socketDisconnected();
|
||||
void socketError(QAbstractSocket::SocketError e);
|
||||
|
||||
mtpBuffer handleResponse(const char *packet, uint32 length);
|
||||
mtpBuffer parsePacket(bytes::const_span bytes);
|
||||
static void handleError(QAbstractSocket::SocketError e, QTcpSocket &sock);
|
||||
static uint32 fourCharsToUInt(char ch1, char ch2, char ch3, char ch4) {
|
||||
char ch[4] = { ch1, ch2, ch3, ch4 };
|
||||
|
Loading…
Reference in New Issue
Block a user