1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-12-03 18:17:45 +01:00
libtgvoip/controller/protocol/PacketStructs.cpp

152 lines
4.9 KiB
C++
Raw Normal View History

2020-03-17 20:11:27 +01:00
#include "PacketStructs.h"
#include "../PrivateDefines.cpp"
using namespace tgvoip;
2020-03-18 19:54:56 +01:00
bool Packet::parse(const BufferInputStream &in, const VersionInfo &ver)
2020-03-17 20:11:27 +01:00
{
2020-03-18 19:54:56 +01:00
if (!ver.isNew())
2020-03-17 20:11:27 +01:00
{
2020-03-18 21:43:44 +01:00
return parseLegacy(in, ver);
2020-03-17 20:11:27 +01:00
}
}
2020-03-18 21:43:44 +01:00
bool Packet::parseLegacy(const BufferInputStream &in, const VersionInfo &ver)
2020-03-17 20:11:27 +01:00
{
// Version-specific extraction of legacy packet fields ackId (last received packet seq on remote), (incoming packet seq) pseq, (ack mask) acks, (packet type) type, (flags) pflags, packet length
uint32_t ackId; // Last received packet seqno on remote
uint32_t pseq; // Incoming packet seqno
uint32_t acks; // Ack mask
unsigned char type, pflags; // Packet type, flags
size_t packetInnerLen = 0;
2020-03-18 21:43:44 +01:00
if (ver.peerVersion >= 8)
2020-03-17 20:11:27 +01:00
{
2020-03-18 21:43:44 +01:00
if (!(
in.TryRead(type) &&
in.TryRead(ackId) &&
in.TryRead(pseq) &&
in.TryRead(acks) &&
in.TryRead(pflags)))
return false;
2020-03-17 20:11:27 +01:00
packetInnerLen = in.Remaining();
}
2020-03-18 21:43:44 +01:00
else if (!parseLegacyLegacy(in, type, ackId, pseq, acks, pflags, packetInnerLen, ver.peerVersion))
2020-03-17 20:11:27 +01:00
{
return false;
}
this->seq = pseq;
this->ackSeq = ackId;
this->ackMask = acks;
// Extra data
if (pflags & XPFLAG_HAS_EXTRA)
{
2020-03-18 21:43:44 +01:00
if (!in.TryRead(extraSignaling, ver))
return false;
2020-03-17 20:11:27 +01:00
}
if (pflags & XPFLAG_HAS_RECV_TS)
{
2020-03-18 21:43:44 +01:00
if (!in.TryRead(recvTS))
return false;
2020-03-17 20:11:27 +01:00
}
2020-03-18 21:43:44 +01:00
if (auto extra = Extra::chooseFromType(type))
2020-03-17 20:11:27 +01:00
{
2020-03-18 21:43:44 +01:00
if (!extra->parse(in, ver))
return false;
extraSignaling.v.push_back(Wrapped<Extra>(std::move(extra)));
streamId = 0;
2020-03-17 20:11:27 +01:00
}
2020-03-18 21:43:44 +01:00
else if (type == PKT_STREAM_EC)
2020-03-17 20:11:27 +01:00
{
}
2020-03-18 21:43:44 +01:00
else if (type == PKT_STREAM_DATA || type == PKT_STREAM_DATA_X2 || type == PKT_STREAM_DATA_X3)
2020-03-17 20:11:27 +01:00
{
}
}
2020-03-18 21:43:44 +01:00
bool Packet::parseLegacyLegacy(const BufferInputStream &in, unsigned char &type, uint32_t &ackId, uint32_t &pseq, uint32_t &acks, unsigned char &pflags, size_t &packetInnerLen, int peerVersion)
2020-03-17 20:11:27 +01:00
{
size_t packetInnerLen = 0;
uint32_t tlid = in.ReadUInt32();
if (tlid == TLID_DECRYPTED_AUDIO_BLOCK)
{
in.ReadInt64(); // random id
uint32_t randLen = in.ReadTlLength();
in.Seek(in.GetOffset() + randLen + pad4(randLen));
uint32_t flags = in.ReadUInt32();
type = (unsigned char)((flags >> 24) & 0xFF);
if (!(flags & LEGACY_PFLAG_HAS_SEQ && flags & LEGACY_PFLAG_HAS_RECENT_RECV))
{
LOGW("Received packet doesn't have LEGACY_PFLAG_HAS_SEQ, LEGACY_PFLAG_HAS_RECENT_RECV, or both");
return false;
}
// These are all errors that weren't even used in the first place in newer protocols.
// Also, a call cannot possibly have a wrong call ID and correct encryption key (unless there's some shady legacy stuff that's going on, but for now I won't even consider it).
/*
if (flags & LEGACY_PFLAG_HAS_CALL_ID)
{
unsigned char pktCallID[16];
in.ReadBytes(pktCallID, 16);
if (memcmp(pktCallID, callID, 16) != 0)
{
LOGW("Received packet has wrong call id");
// These are all errors that weren't even used in the first place in newer protocols
//lastError = ERROR_UNKNOWN;
//SetState(STATE_FAILED);
return false;
}
}*/
ackId = in.ReadUInt32();
pseq = in.ReadUInt32();
acks = in.ReadUInt32();
if (flags & LEGACY_PFLAG_HAS_PROTO)
{
uint32_t proto = in.ReadUInt32();
if (proto != PROTOCOL_NAME)
{
LOGW("Received packet uses wrong protocol");
// These are all errors that weren't even used in the first place in newer protocols
//lastError = ERROR_INCOMPATIBLE;
//SetState(STATE_FAILED);
return false;
}
}
if (flags & LEGACY_PFLAG_HAS_EXTRA)
{
uint32_t extraLen = in.ReadTlLength();
in.Seek(in.GetOffset() + extraLen + pad4(extraLen));
}
if (flags & LEGACY_PFLAG_HAS_DATA)
{
packetInnerLen = in.ReadTlLength();
}
pflags = 0;
}
else if (tlid == TLID_SIMPLE_AUDIO_BLOCK)
{
in.ReadInt64(); // random id
uint32_t randLen = in.ReadTlLength();
in.Seek(in.GetOffset() + randLen + pad4(randLen));
packetInnerLen = in.ReadTlLength();
type = in.ReadByte();
ackId = in.ReadUInt32();
pseq = in.ReadUInt32();
acks = in.ReadUInt32();
if (peerVersion >= 6)
pflags = in.ReadByte();
else
pflags = 0;
}
else
{
LOGW("Received a packet of unknown type %08X", tlid);
return false;
}
return true;
}