mirror of
https://github.com/danog/libtgvoip.git
synced 2024-11-30 04:39:03 +01:00
Save
This commit is contained in:
parent
d2814499ee
commit
ecd7bc3cef
@ -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 \
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -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,
|
||||
|
@ -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;
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user