1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-11-29 20:29:01 +01:00
This commit is contained in:
Daniil Gentili 2020-03-18 21:43:44 +01:00
parent d2814499ee
commit ecd7bc3cef
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
9 changed files with 157 additions and 69 deletions

View File

@ -21,7 +21,7 @@ controller/audio/AudioPacketSender.cpp \
controller/net/PacketReassembler.cpp \
controller/protocol/PacketManager.cpp \
controller/protocol/PacketStructs.cpp \
controller/protocol/packets/Interface.cpp \
controller/protocol/packets/Extra.cpp \
VoIPGroupController.cpp \
VoIPServerConfig.cpp \
audio/AudioIO.cpp \

View File

@ -7,11 +7,11 @@ bool Packet::parse(const BufferInputStream &in, const VersionInfo &ver)
{
if (!ver.isNew())
{
return parseLegacyPacket(in, ver);
return parseLegacy(in, ver);
}
}
bool Packet::parseLegacyPacket(const BufferInputStream &in, const VersionInfo &ver)
bool Packet::parseLegacy(const BufferInputStream &in, const VersionInfo &ver)
{
// 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
@ -19,16 +19,18 @@ bool Packet::parseLegacyPacket(const BufferInputStream &in, const VersionInfo &v
uint32_t acks; // Ack mask
unsigned char type, pflags; // Packet type, flags
size_t packetInnerLen = 0;
if (peerVersion >= 8)
if (ver.peerVersion >= 8)
{
type = in.ReadByte();
ackId = in.ReadUInt32();
pseq = in.ReadUInt32();
acks = in.ReadUInt32();
pflags = in.ReadByte();
if (!(
in.TryRead(type) &&
in.TryRead(ackId) &&
in.TryRead(pseq) &&
in.TryRead(acks) &&
in.TryRead(pflags)))
return false;
packetInnerLen = in.Remaining();
}
else if (!legacyParsePacket(in, type, ackId, pseq, acks, pflags, packetInnerLen, peerVersion))
else if (!parseLegacyLegacy(in, type, ackId, pseq, acks, pflags, packetInnerLen, ver.peerVersion))
{
return false;
}
@ -39,31 +41,31 @@ bool Packet::parseLegacyPacket(const BufferInputStream &in, const VersionInfo &v
// Extra data
if (pflags & XPFLAG_HAS_EXTRA)
{
extras.parse(in, peerVersion);
if (!in.TryRead(extraSignaling, ver))
return false;
}
if (pflags & XPFLAG_HAS_RECV_TS)
{
recvTS = in.ReadUInt32();
if (!in.TryRead(recvTS))
return false;
}
if (type == PKT_INIT)
if (auto extra = Extra::chooseFromType(type))
{
Buffer
if (!extra->parse(in, ver))
return false;
extraSignaling.v.push_back(Wrapped<Extra>(std::move(extra)));
streamId = 0;
}
else if (type == PKT_INIT_ACK)
else if (type == PKT_STREAM_EC)
{
}
else if (type == PKT_PING)
{
}
else if (type == PKT_PONG)
{
}
else if (type == PKT_NOP)
else if (type == PKT_STREAM_DATA || type == PKT_STREAM_DATA_X2 || type == PKT_STREAM_DATA_X3)
{
}
}
bool legacyParsePacket(const BufferInputStream &in, unsigned char &type, uint32_t &ackId, uint32_t &pseq, uint32_t &acks, unsigned char &pflags, size_t &packetInnerLen, int peerVersion)
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)
{
size_t packetInnerLen = 0;
uint32_t tlid = in.ReadUInt32();

View File

@ -9,19 +9,23 @@ namespace tgvoip
{
class PacketSender;
struct Packet : public Serializable
struct Packet : public Serializable, SingleChoice<Packet>
{
public:
virtual bool parse(const BufferInputStream &in, const VersionInfo &ver) override;
virtual void serialize(BufferOutputStream &out, const VersionInfo &ver) override;
bool parse(const BufferInputStream &in, const VersionInfo &ver) override;
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override;
private:
bool parseLegacy(const BufferInputStream &in, const VersionInfo &ver);
bool parseLegacyLegacy(const BufferInputStream &in, unsigned char &type, uint32_t &ackId, uint32_t &pseq, uint32_t &acks, unsigned char &pflags, size_t &packetInnerLen, int peerVersion);
public:
enum Flags : uint8_t
{
Len16 = 1,
ExtraFEC = 2,
ExtraSignaling = 4,
RecvTS = 8
RecvTS = 2,
ExtraFEC = 4,
ExtraSignaling = 8
};
enum EFlags : uint8_t
{
@ -41,17 +45,8 @@ public:
Buffer data;
Array<Extra> extras;
};
struct PacketLegacy : public Packet
{
public:
bool parse(const BufferInputStream &in, const VersionInfo &ver) override;
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override;
private:
bool parseLegacyLegacyPacket(const BufferInputStream &in, unsigned char &type, uint32_t &ackId, uint32_t &pseq, uint32_t &acks, unsigned char &pflags, size_t &packetInnerLen, int peerVersion);
Array<Bytes> extraEC;
Array<Wrapped<Extra>> extraSignaling;
};
// Legacy stuff

View File

@ -46,7 +46,37 @@ std::shared_ptr<Extra> Extra::choose(const BufferInputStream &in, const VersionI
return std::make_shared<ExtraGroupCallKey>();
case ExtraGroupCallUpgrade::ID:
return std::make_shared<ExtraGroupCallUpgrade>();
case ExtraInit::ID:
return std::make_shared<ExtraInit>();
case ExtraInitAck::ID:
return std::make_shared<ExtraInitAck>();
case ExtraPing::ID:
return std::make_shared<ExtraPing>();
case ExtraPong::ID:
return std::make_shared<ExtraPong>();
}
return nullptr;
}
std::shared_ptr<Extra> Extra::chooseFromType(int type)
{
switch (type)
{
case PKT_INIT:
return std::make_shared<ExtraInit>();
case PKT_INIT_ACK:
return std::make_shared<ExtraInitAck>();
case PKT_LAN_ENDPOINT:
return std::make_shared<ExtraLanEndpoint>();
case PKT_NETWORK_CHANGED:
return std::make_shared<ExtraNetworkChanged>();
case PKT_PING:
return std::make_shared<ExtraPing>();
case PKT_PONG:
return std::make_shared<ExtraPong>();
case PKT_STREAM_STATE:
return std::make_shared<ExtraStreamFlags>();
}
return nullptr;
}
bool StreamInfo::parse(const BufferInputStream &in, const VersionInfo &ver)
@ -69,6 +99,15 @@ void StreamInfo::serialize(BufferOutputStream &out, const VersionInfo &ver) cons
bool ExtraStreamFlags::parse(const BufferInputStream &in, const VersionInfo &ver)
{
if (ver.peerVersion < 6)
{
if (!in.TryRead(streamId))
return false;
if (!in.TryRead(flags))
return false;
flags = flags ? Flags::Enabled : 0;
return true;
}
return in.TryRead(streamId) &&
ver.isNew()
? in.TryRead(flags)
@ -80,8 +119,10 @@ void ExtraStreamFlags::serialize(BufferOutputStream &out, const VersionInfo &ver
if (ver.isNew())
out.WriteByte(flags);
else
else if (ver.peerVersion >= 6)
out.WriteUInt32(flags);
else
out.WriteByte(flags & Flags::Enabled);
}
bool ExtraStreamCsd::parse(const BufferInputStream &in, const VersionInfo &ver)
@ -151,12 +192,12 @@ void ExtraInit::serialize(BufferOutputStream &out, const VersionInfo &ver) const
{
out.WriteByte(2); // audio codecs count, for some reason two codecs required
out.WriteByte(CODEC_OPUS_OLD);
out.WriteByte(0); // second useless codec
out.WriteByte(0); // what is this
out.WriteByte(0); // what is this
out.WriteByte(0); // second useless codec
out.WriteByte(0); // what is this
out.WriteByte(0); // what is this
out.WriteInt32(CODEC_OPUS); // WHAT IS THIS
out.WriteByte(0); // video codecs count (decode)
out.WriteByte(0); // video codecs count (encode)
out.WriteByte(0); // video codecs count (decode)
out.WriteByte(0); // video codecs count (encode)
}
else
{
@ -178,3 +219,26 @@ void ExtraInitAck::serialize(BufferOutputStream &out, const VersionInfo &ver) co
out.WriteUInt32(minVersion);
out.Write(streams, ver);
}
bool ExtraPong::parse(const BufferInputStream &in, const VersionInfo &ver)
{
return in.TryRead(seq);
}
void ExtraPong::serialize(BufferOutputStream &out, const VersionInfo &ver) const
{
out.WriteUInt32(seq);
}
bool ExtraNetworkChanged::parse(const BufferInputStream &in, const VersionInfo &ver)
{
return in.TryRead(streamId) &&
ver.isNew()
? in.TryRead(flags)
: in.TryReadCompat<uint32_t>(flags);
}
void ExtraNetworkChanged::serialize(BufferOutputStream &out, const VersionInfo &ver) const
{
out.WriteByte(streamId);
ver.isNew() ? out.WriteByte(flags) : out.WriteUInt32(flags);
}

View File

@ -6,12 +6,12 @@
namespace tgvoip
{
struct Extra : public Serializable
struct Extra : public Serializable, MultiChoice<Extra>
{
static std::shared_ptr<Extra> choose(const BufferInputStream &in, const VersionInfo &ver);
static std::shared_ptr<T> chooseFromType(uint8_t type);
};
struct Codec : public Serializable, SingleChoice<StreamInfo>
struct Codec : public Serializable, SingleChoice<Codec>
{
public:
bool parse(const BufferInputStream &in, const VersionInfo &ver) override;
@ -115,6 +115,7 @@ struct ExtraNetworkChanged : public Extra
DataSavingEnabled = 1
};
uint8_t streamId = 0;
uint8_t flags = 0;
static const uint8_t ID = 4;
@ -176,4 +177,20 @@ struct ExtraInitAck : public Extra
static const uint8_t ID = 8;
};
struct ExtraPing : public Extra
{
bool parse(const BufferInputStream &in, const VersionInfo &ver) override { return true; };
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override{};
static const uint8_t ID = 9;
};
struct ExtraPong : public Extra
{
bool parse(const BufferInputStream &in, const VersionInfo &ver) override;
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override;
uint32_t seq = 0;
static const uint8_t ID = 9;
};
} // namespace tgvoip

View File

@ -26,6 +26,13 @@ struct SingleChoice
}
};
template <typename T>
struct MultiChoice
{
static std::shared_ptr<T> choose(const BufferInputStream &in, const VersionInfo &ver);
};
struct Serializable
{
public:
@ -46,48 +53,52 @@ struct Array : public Serializable, SingleChoice<Array<T>>
v.reserve(extraCount);
for (auto i = 0; i < extraCount; i++)
{
auto ptr = T::choose(in, ver);
if (!ptr || !ptr->parse(in, ver))
T data;
if (!data.parse(in, ver))
{
return false;
}
v.push_back(std::move(ptr));
v.push_back(std::move(data));
}
return true;
}
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override
{
out.WriteByte(v.size());
for (auto &ptr : v)
for (auto &data : v)
{
ptr->serialize(out, ver);
data.serialize(out, ver);
}
}
std::vector<std::shared_ptr<T>> v;
std::vector<T> v;
};
template <class T>
struct Wrapped : public Serializable, SingleChoice<Wrapped>
struct Wrapped : public Serializable, SingleChoice<Wrapped<T>>
{
Wrapped(std::shared_ptr &&_d) : d(_d);
Wrapped(std::shared_ptr &_d) : d(_d);
bool parse(const BufferInputStream &in, const VersionInfo &ver) override
{
uint8_t len;
if (!in.TryRead(len))
return false;
return d.parse(in.GetPartBuffer(len));
d = T::choose(in, ver);
return d->parse(in.GetPartBuffer(len));
}
void serialize(BufferOutputStream &out, const VersionInfo &ver) const override
{
out.Advance(1);
size_t len = out.GetOffset();
d.serialize(out, ver);
d->serialize(out, ver);
len = out.GetOffset() - len;
out.Rewind(len + 1);
out.WriteByte(len);
out.Advance(len);
}
T d;
std::shared_ptr<T> d;
};
struct Bytes : public Serializable,

View File

@ -21,9 +21,9 @@ packet$_
data:bytes // No PTS, simply use the seq
extraFEC:flags.1?ExtraFEC
extraSignaling:flags.2?Extras<ExtraSignaling>
recvTS:flags.3?int
recvTS:flags.1?int
extraFEC:flags.2?ExtraFEC
extraSignaling:flags.3?Extras<ExtraSignaling>
= Packet;
@ -39,7 +39,7 @@ extraStreamCsd#02 streamId:(## 8) width:(## 16) height:(## 16) count:(## 8) [ le
extraLanEndpoint#03 address:# port:(## 16) = ExtraSignaling;
extraIpv6Endpoint#07 address:(## 128) port:(## 16) = ExtraSignaling;
extraNetworkChanged#04 flags:(## 8) dataSavingEnabled:flags.0?true = ExtraSignaling;
extraNetworkChanged#04 streamId:(## 8) flags:(## 8) dataSavingEnabled:flags.0?true = ExtraSignaling;
extraGroupCallKey#05 key:(## 256) = ExtraSignaling;
extraGroupCallUpgrade#06 = ExtraSignaling;
@ -55,7 +55,5 @@ extraInitAck#09 peerVersion:# minVersion:# streams:Extras<StreamInfo> = ExtraSig
extraPing#A = ExtraSignaling;
extraPong#B seq:# = ExtraSignaling;
extraNop#C = ExtraSignaling;
// Stream info
streamInfo$_ streamId:(## 8) type:(## 8) codec:# frameDurationIgnored:(## 16) enabled:(## 8)= StreamInfo;

View File

@ -357,6 +357,10 @@ void BufferOutputStream::WriteBytes(const Buffer &buffer, size_t offset, size_t
WriteBytes(*buffer + offset, count);
}
void BufferOutputStream::Write(const Serializable &data, const VersionInfo &ver)
{
data.serialize(*this, ver);
}
unsigned char *BufferOutputStream::GetBuffer()
{

View File

@ -105,10 +105,7 @@ public:
void WriteBytes(const unsigned char *bytes, size_t count);
void WriteBytes(const Buffer &buffer);
void WriteBytes(const Buffer &buffer, size_t offset, size_t count);
inline void Write(const Serializable &data, const VersionInfo &ver)
{
data.serialize(*this, ver);
}
void Write(const Serializable &data, const VersionInfo &ver);
unsigned char *GetBuffer();
size_t GetOffset();
size_t GetLength();