mirror of
https://github.com/danog/libtgvoip.git
synced 2024-11-29 20:29:01 +01:00
Begin refactoring protocol structures
This commit is contained in:
parent
bbe8734bba
commit
16ff209ff7
@ -20,6 +20,7 @@ controller/audio/OpusEncoder.cpp \
|
||||
controller/audio/AudioPacketSender.cpp \
|
||||
controller/net/PacketReassembler.cpp \
|
||||
controller/protocol/PacketManager.cpp \
|
||||
controller/protocol/PacketStructs.cpp \
|
||||
VoIPGroupController.cpp \
|
||||
VoIPServerConfig.cpp \
|
||||
audio/AudioIO.cpp \
|
||||
|
16
Makefile.in
16
Makefile.in
@ -818,7 +818,8 @@ am__libtgvoip_la_SOURCES_DIST = TgVoip.cpp VoIPController.cpp \
|
||||
controller/audio/OpusEncoder.cpp \
|
||||
controller/audio/AudioPacketSender.cpp \
|
||||
controller/net/PacketReassembler.cpp \
|
||||
controller/protocol/PacketManager.cpp VoIPGroupController.cpp \
|
||||
controller/protocol/PacketManager.cpp \
|
||||
controller/protocol/PacketStructs.cpp VoIPGroupController.cpp \
|
||||
VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \
|
||||
audio/AudioOutput.cpp audio/Resampler.cpp \
|
||||
audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \
|
||||
@ -1759,7 +1760,8 @@ am__objects_12 = TgVoip.lo VoIPController.lo tools/Buffers.lo \
|
||||
controller/audio/OpusEncoder.lo \
|
||||
controller/audio/AudioPacketSender.lo \
|
||||
controller/net/PacketReassembler.lo \
|
||||
controller/protocol/PacketManager.lo VoIPGroupController.lo \
|
||||
controller/protocol/PacketManager.lo \
|
||||
controller/protocol/PacketStructs.lo VoIPGroupController.lo \
|
||||
VoIPServerConfig.lo audio/AudioIO.lo audio/AudioInput.lo \
|
||||
audio/AudioOutput.lo audio/Resampler.lo \
|
||||
audio/AudioInputTester.lo os/posix/NetworkSocketPosix.lo \
|
||||
@ -2076,6 +2078,7 @@ am__depfiles_remade = ./$(DEPDIR)/TgVoip.Plo \
|
||||
controller/net/$(DEPDIR)/NetworkSocket.Plo \
|
||||
controller/net/$(DEPDIR)/PacketReassembler.Plo \
|
||||
controller/protocol/$(DEPDIR)/PacketManager.Plo \
|
||||
controller/protocol/$(DEPDIR)/PacketStructs.Plo \
|
||||
os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo \
|
||||
os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo \
|
||||
os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo \
|
||||
@ -2393,7 +2396,8 @@ SRC = TgVoip.cpp VoIPController.cpp tools/Buffers.cpp \
|
||||
controller/audio/OpusEncoder.cpp \
|
||||
controller/audio/AudioPacketSender.cpp \
|
||||
controller/net/PacketReassembler.cpp \
|
||||
controller/protocol/PacketManager.cpp VoIPGroupController.cpp \
|
||||
controller/protocol/PacketManager.cpp \
|
||||
controller/protocol/PacketStructs.cpp VoIPGroupController.cpp \
|
||||
VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \
|
||||
audio/AudioOutput.cpp audio/Resampler.cpp \
|
||||
audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \
|
||||
@ -2571,6 +2575,9 @@ controller/protocol/$(DEPDIR)/$(am__dirstamp):
|
||||
controller/protocol/PacketManager.lo: \
|
||||
controller/protocol/$(am__dirstamp) \
|
||||
controller/protocol/$(DEPDIR)/$(am__dirstamp)
|
||||
controller/protocol/PacketStructs.lo: \
|
||||
controller/protocol/$(am__dirstamp) \
|
||||
controller/protocol/$(DEPDIR)/$(am__dirstamp)
|
||||
audio/$(am__dirstamp):
|
||||
@$(MKDIR_P) audio
|
||||
@: > audio/$(am__dirstamp)
|
||||
@ -4039,6 +4046,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@controller/net/$(DEPDIR)/NetworkSocket.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@controller/net/$(DEPDIR)/PacketReassembler.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@controller/protocol/$(DEPDIR)/PacketManager.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@controller/protocol/$(DEPDIR)/PacketStructs.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo@am__quote@ # am--include-marker
|
||||
@ -4929,6 +4937,7 @@ distclean: distclean-am
|
||||
-rm -f controller/net/$(DEPDIR)/NetworkSocket.Plo
|
||||
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
||||
-rm -f controller/protocol/$(DEPDIR)/PacketManager.Plo
|
||||
-rm -f controller/protocol/$(DEPDIR)/PacketStructs.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo
|
||||
@ -5299,6 +5308,7 @@ maintainer-clean: maintainer-clean-am
|
||||
-rm -f controller/net/$(DEPDIR)/NetworkSocket.Plo
|
||||
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
||||
-rm -f controller/protocol/$(DEPDIR)/PacketManager.Plo
|
||||
-rm -f controller/protocol/$(DEPDIR)/PacketStructs.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
||||
-rm -f os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo
|
||||
|
@ -62,7 +62,6 @@ enum ProtocolVersions
|
||||
// Extra packet flags
|
||||
#define XPFLAG_HAS_EXTRA 1 // Signaling
|
||||
#define XPFLAG_HAS_RECV_TS 2 // Video calls
|
||||
#define XPFLAG_HAS_TRANSPORT_ID 4 // TODO: remove, not used
|
||||
|
||||
|
||||
// Extra signaling packet types
|
||||
@ -74,6 +73,9 @@ enum ProtocolVersions
|
||||
#define EXTRA_TYPE_REQUEST_GROUP 6
|
||||
#define EXTRA_TYPE_IPV6_ENDPOINT 7
|
||||
|
||||
#define EXTRA_TYPE_INIT 8
|
||||
#define EXTRA_TYPE_INIT_ACK 9
|
||||
|
||||
// Stream signaling flags
|
||||
#define STREAM_FLAG_ENABLED 1
|
||||
#define STREAM_FLAG_DTX 2
|
||||
|
@ -38,7 +38,7 @@ size_t VoIPController::decryptPacket(unsigned char *buffer, BufferInputStream &i
|
||||
else
|
||||
{
|
||||
memcpy(buffer + in.GetOffset(), aesOut, in.Remaining());
|
||||
in.ReadInt32();
|
||||
return in.ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ void JitterBuffer::PutInternal(const jitter_packet_t &pkt, bool overwriteExistin
|
||||
slot->buffer = bufferPool.Get();
|
||||
slot->recvTimeDiff = time - prevRecvTime;
|
||||
slot->isEC = pkt.isEC;
|
||||
slot->buffer.CopyFromOtherBuffer(pkt.buffer, pkt.size);
|
||||
slot->buffer.CopyFromOtherBuffer(pkt.buffer, pkt.size); // This prevents undefined behaviour
|
||||
#ifdef TGVOIP_DUMP_JITTER_STATS
|
||||
fprintf(dump, "%u\t%.03f\t%d\t%.03f\t%.03f\t%.03f\n", pkt.timestamp, time, GetCurrentDelay(), lastMeasuredJitter, lastMeasuredDelay, minDelay);
|
||||
#endif
|
||||
|
@ -204,6 +204,13 @@ NetworkAddress NetworkAddress::IPv4(uint32_t addr)
|
||||
a.addr.ipv4 = addr;
|
||||
return a;
|
||||
}
|
||||
NetworkAddress NetworkAddress::IPv4(const BufferInputStream &in)
|
||||
{
|
||||
NetworkAddress a;
|
||||
a.isIPv6 = false;
|
||||
a.addr.ipv4 = in.ReadUInt32();
|
||||
return a;
|
||||
}
|
||||
|
||||
NetworkAddress NetworkAddress::IPv6(std::string str)
|
||||
{
|
||||
@ -224,6 +231,13 @@ NetworkAddress NetworkAddress::IPv6(const uint8_t addr[16])
|
||||
memcpy(a.addr.ipv6, addr, 16);
|
||||
return a;
|
||||
}
|
||||
NetworkAddress NetworkAddress::IPv6(const BufferInputStream &in)
|
||||
{
|
||||
NetworkAddress a;
|
||||
a.isIPv6 = true;
|
||||
in.ReadBytes(a.addr.ipv6, 16);
|
||||
return a;
|
||||
}
|
||||
|
||||
bool NetworkSocket::Select(std::vector<std::shared_ptr<NetworkSocket>> &readFds, std::vector<std::shared_ptr<NetworkSocket>> &writeFds, std::vector<std::shared_ptr<NetworkSocket>> &errorFds, const std::unique_ptr<SocketSelectCanceller> &canceller)
|
||||
{
|
||||
|
@ -57,8 +57,10 @@ public:
|
||||
static NetworkAddress Empty();
|
||||
static NetworkAddress IPv4(std::string str);
|
||||
static NetworkAddress IPv4(uint32_t addr);
|
||||
static NetworkAddress IPv4(const BufferInputStream &in);
|
||||
static NetworkAddress IPv6(std::string str);
|
||||
static NetworkAddress IPv6(const uint8_t addr[16]);
|
||||
static NetworkAddress IPv6(const BufferInputStream &in);
|
||||
|
||||
bool isIPv6 = false;
|
||||
union {
|
||||
|
@ -3,84 +3,6 @@
|
||||
using namespace tgvoip;
|
||||
using namespace std;
|
||||
|
||||
bool VoIPController::legacyParsePacket(const BufferInputStream &in, unsigned char &type, uint32_t &ackId, uint32_t &pseq, uint32_t &acks, unsigned char &pflags, size_t &packetInnerLen)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void VoIPController::legacyWritePacketHeader(uint32_t pseq, uint32_t acks, BufferOutputStream *s, unsigned char type, uint32_t length)
|
||||
{
|
||||
|
@ -438,17 +438,16 @@ void VoIPController::SendExtra(Buffer &data, unsigned char type)
|
||||
ENFORCE_MSG_THREAD;
|
||||
|
||||
LOGV("Sending extra type %u length %u", type, (unsigned int)data.Length());
|
||||
for (vector<UnacknowledgedExtraData>::iterator x = currentExtras.begin(); x != currentExtras.end(); ++x)
|
||||
for (auto &extra : currentExtras)
|
||||
{
|
||||
if (x->type == type)
|
||||
if (extra.type == type)
|
||||
{
|
||||
x->firstContainingSeq = 0;
|
||||
x->data = move(data);
|
||||
extra.firstContainingSeq = 0;
|
||||
extra.data = move(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
UnacknowledgedExtraData xd = {type, move(data), 0};
|
||||
currentExtras.push_back(move(xd));
|
||||
currentExtras.push_back(UnacknowledgedExtraData{type, move(data), 0});
|
||||
}
|
||||
|
||||
void VoIPController::SendUdpPing(Endpoint &endpoint)
|
||||
|
183
controller/protocol/PacketStructs.cpp
Normal file
183
controller/protocol/PacketStructs.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
#include "PacketStructs.h"
|
||||
#include "../PrivateDefines.cpp"
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
std::shared_ptr<Extra> choose(const BufferInputStream &in, int peerVersion)
|
||||
{
|
||||
switch (in.ReadByte())
|
||||
{
|
||||
case ExtraStreamFlags::ID:
|
||||
return std::make_shared<ExtraStreamFlags>();
|
||||
case ExtraStreamCsd::ID:
|
||||
return std::make_shared<ExtraStreamCsd>();
|
||||
case ExtraLanEndpoint::ID:
|
||||
return std::make_shared<ExtraLanEndpoint>();
|
||||
case ExtraIpv6Endpoint::ID:
|
||||
return std::make_shared<ExtraIpv6Endpoint>();
|
||||
case ExtraNetworkChanged::ID:
|
||||
return std::make_shared<ExtraNetworkChanged>();
|
||||
case ExtraGroupCallKey::ID:
|
||||
return std::make_shared<ExtraGroupCallKey>();
|
||||
case ExtraGroupCallUpgrade::ID:
|
||||
return std::make_shared<ExtraGroupCallUpgrade>();
|
||||
}
|
||||
}
|
||||
|
||||
bool Packet::parse(const BufferInputStream &in, int peerVersion)
|
||||
{
|
||||
if (peerVersion < PROTOCOL_RELIABLE)
|
||||
{
|
||||
return parseLegacyPacket(in, peerVersion);
|
||||
}
|
||||
}
|
||||
|
||||
bool Packet::parseLegacyPacket(const BufferInputStream &in, int peerVersion)
|
||||
{
|
||||
// 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;
|
||||
if (peerVersion >= 8)
|
||||
{
|
||||
type = in.ReadByte();
|
||||
ackId = in.ReadUInt32();
|
||||
pseq = in.ReadUInt32();
|
||||
acks = in.ReadUInt32();
|
||||
pflags = in.ReadByte();
|
||||
packetInnerLen = in.Remaining();
|
||||
}
|
||||
else if (!legacyParsePacket(in, type, ackId, pseq, acks, pflags, packetInnerLen, peerVersion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this->seq = pseq;
|
||||
this->ackSeq = ackId;
|
||||
this->ackMask = acks;
|
||||
|
||||
// Extra data
|
||||
if (pflags & XPFLAG_HAS_EXTRA)
|
||||
{
|
||||
uint8_t extraCount = in.ReadByte();
|
||||
extras.reserve(extraCount);
|
||||
for (auto i = 0; i < extraCount; i++)
|
||||
{
|
||||
BufferInputStream inExtra = in.GetPartBuffer(in.ReadByte());
|
||||
|
||||
auto ptr = Extra::choose(inExtra, peerVersion);
|
||||
|
||||
if (ptr->parse(inExtra, peerVersion))
|
||||
{
|
||||
extras.push_back(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pflags & XPFLAG_HAS_RECV_TS)
|
||||
{
|
||||
recvTS = in.ReadUInt32();
|
||||
}
|
||||
|
||||
if (type == PKT_INIT)
|
||||
{
|
||||
Buffer
|
||||
}
|
||||
else if (type == PKT_INIT_ACK)
|
||||
{
|
||||
}
|
||||
else if (type == PKT_PING)
|
||||
{
|
||||
}
|
||||
else if (type == PKT_PONG)
|
||||
{
|
||||
}
|
||||
else if (type == PKT_NOP)
|
||||
{
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
@ -6,18 +6,207 @@
|
||||
namespace tgvoip
|
||||
{
|
||||
class PacketSender;
|
||||
struct Packet
|
||||
struct Serializable
|
||||
{
|
||||
virtual bool parse(const BufferInputStream &in, int peerVersion) = 0;
|
||||
virtual bool serialize(BufferOutputStream &out, int peerVersion) = 0;
|
||||
};
|
||||
template <typename T>
|
||||
struct Array
|
||||
{
|
||||
public:
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
std::vector<std::shared_ptr<T>> contents;
|
||||
};
|
||||
|
||||
struct Extra : public Serializable
|
||||
{
|
||||
static std::shared_ptr<Extra> choose(const BufferInputStream &in, int peerVersion);
|
||||
};
|
||||
struct Packet : public Serializable
|
||||
{
|
||||
public:
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
private:
|
||||
bool parseLegacyPacket(const BufferInputStream &in, int peerVersion);
|
||||
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);
|
||||
|
||||
public:
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
Len16 = 1,
|
||||
ExtraFEC = 2,
|
||||
ExtraSignaling = 4,
|
||||
RecvTS = 8
|
||||
};
|
||||
enum EFlags : uint8_t
|
||||
{
|
||||
Fragmented = 1,
|
||||
Keyframe = 2
|
||||
};
|
||||
|
||||
uint32_t seq;
|
||||
uint32_t ackSeq;
|
||||
uint32_t ackMask;
|
||||
|
||||
uint8_t streamId;
|
||||
uint8_t flags;
|
||||
uint8_t flags = 0;
|
||||
uint8_t eFlags = 0;
|
||||
|
||||
uint32_t recvTS = 0;
|
||||
|
||||
Buffer data;
|
||||
uint8_t eFlags = 0;
|
||||
|
||||
std::vector<std::shared_ptr<Extra>> extras;
|
||||
};
|
||||
|
||||
struct StreamInfo : public Serializable
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<StreamInfo> choose(const BufferInputStream &in, int peerVersion)
|
||||
{
|
||||
return std::make_shared<StreamInfo>();
|
||||
};
|
||||
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
uint8_t streamId = 0;
|
||||
uint8_t type = 0;
|
||||
uint32_t codec = 0;
|
||||
uint16_t frameDuration = 0;
|
||||
uint8_t enabled = 0;
|
||||
};
|
||||
|
||||
struct ExtraStreamFlags : public Extra
|
||||
{
|
||||
public:
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
Enabled = 1,
|
||||
Dtx = 2,
|
||||
ExtraEC = 3,
|
||||
Paused = 4
|
||||
};
|
||||
|
||||
uint8_t flags = 0;
|
||||
|
||||
static const uint8_t ID = 1;
|
||||
};
|
||||
|
||||
struct ExtraStreamCsd : public Extra
|
||||
{
|
||||
public:
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
|
||||
std::vector<BufferInputStream> data;
|
||||
|
||||
static const uint8_t ID = 2;
|
||||
};
|
||||
|
||||
struct ExtraLanEndpoint : public Extra
|
||||
{
|
||||
public:
|
||||
virtual bool parse(const BufferInputStream &in, int peerVersion);
|
||||
virtual bool serialize(BufferOutputStream &out, int peerVersion);
|
||||
|
||||
NetworkAddress address;
|
||||
uint16_t port = 0;
|
||||
|
||||
static const uint8_t ID = 3;
|
||||
};
|
||||
|
||||
struct ExtraIpv6Endpoint : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
NetworkAddress address;
|
||||
uint16_t port = 0;
|
||||
|
||||
static const uint8_t ID = 7;
|
||||
};
|
||||
|
||||
struct ExtraNetworkChanged : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
DataSavingEnabled = 1
|
||||
};
|
||||
|
||||
uint8_t flags = 0;
|
||||
|
||||
static const uint8_t ID = 4;
|
||||
};
|
||||
|
||||
struct ExtraGroupCallKey : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
std::array<uint8_t, 256> key;
|
||||
|
||||
static const uint8_t ID = 5;
|
||||
};
|
||||
|
||||
struct ExtraGroupCallUpgrade : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override{};
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override{};
|
||||
|
||||
static const uint8_t ID = 6;
|
||||
};
|
||||
|
||||
struct ExtraInit : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
DataSavingEnabled = 1,
|
||||
GroupCallSupported = 2,
|
||||
VideoSendSupported = 4,
|
||||
VideoRecvSupported = 8
|
||||
};
|
||||
|
||||
uint32_t peerVersion = 0;
|
||||
uint32_t minVersion = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
std::vector<std::shared_ptr<StreamInfo>> streams;
|
||||
|
||||
static const uint8_t ID = 8;
|
||||
};
|
||||
|
||||
struct ExtraInitAck : public Extra
|
||||
{
|
||||
bool parse(const BufferInputStream &in, int peerVersion) override;
|
||||
bool serialize(BufferOutputStream &out, int peerVersion) override;
|
||||
|
||||
uint32_t peerVersion = 0;
|
||||
uint32_t minVersion = 0;
|
||||
|
||||
std::vector<std::shared_ptr<StreamInfo>> streams;
|
||||
|
||||
static const uint8_t ID = 8;
|
||||
};
|
||||
|
||||
// Legacy stuff
|
||||
struct RecentOutgoingPacket
|
||||
{
|
||||
// For simple NACK reliable resending
|
||||
|
@ -906,10 +906,8 @@ void VoIPController::ProcessExtraData(Buffer &data)
|
||||
{
|
||||
if (!allowP2p)
|
||||
return;
|
||||
unsigned char _addr[16];
|
||||
in.ReadBytes(_addr, 16);
|
||||
NetworkAddress addr = NetworkAddress::IPv6(_addr);
|
||||
uint16_t port = static_cast<uint16_t>(in.ReadInt16());
|
||||
NetworkAddress addr = NetworkAddress::IPv6(in);
|
||||
uint16_t port = in.ReadUInt16();
|
||||
peerIPv6Available = true;
|
||||
LOGV("Received peer IPv6 endpoint [%s]:%u", addr.ToString().c_str(), port);
|
||||
|
||||
@ -964,11 +962,6 @@ uint8_t VoIPController::WritePacketHeader(PendingOutgoingPacket &pkt, BufferOutp
|
||||
|
||||
s.WriteByte(flags);
|
||||
|
||||
if (flags & XPFLAG_HAS_TRANSPORT_ID)
|
||||
{
|
||||
s.WriteByte(manager.getTransportId());
|
||||
}
|
||||
|
||||
if (!currentExtras.empty())
|
||||
{
|
||||
s.WriteByte(static_cast<unsigned char>(currentExtras.size()));
|
||||
|
@ -17,7 +17,7 @@ extraGroupCallUpgrade#06 = ExtraSignaling;
|
||||
streamInfo$_ streamId:(## 8) type:(## 8) codec:# frameDurationIgnored:(## 16) enabled:(## 8)= StreamInfo;
|
||||
|
||||
// Packet
|
||||
packet$_ type:(## 8) ackSeq:# seq:# ackMask:# flags:(## 8) extras:flags.0?Extras<ExtraSignaling> data:payload = Packet;
|
||||
packet$_ type:(## 8) ackSeq:# seq:# ackMask:# flags:(## 8) extras:flags.0?Extras<ExtraSignaling> recvTS:flags.1?int data:payload = Packet;
|
||||
|
||||
payloadInit#0 peerVersion:# minVersion:# flags:# streams:Extras<StreamInfo> dataSavingEnabled:flags.0?true groupCallSupported:flags.1?true videoSendSupported:flags.2?true videoRecvSupported:flags.3?true = Payload;
|
||||
payloadInitAck#1 peerVersion:# minVersion:# streams:Extras<StreamInfo> = Payload;
|
||||
|
@ -23,6 +23,7 @@ packet$_
|
||||
|
||||
extraFEC:flags.1?ExtraFEC
|
||||
extraSignaling:flags.2?Extras<ExtraSignaling>
|
||||
recvTS:flags.3?int
|
||||
|
||||
= Packet;
|
||||
|
||||
@ -32,13 +33,13 @@ extraFEC$_ mask:(## 8) [ length:(## 8) _:bytes ] = ExtraFEC;
|
||||
// Extras
|
||||
extras$_ {t:Type} (## 8) [ length:(## 8) extra:t ] = Extras t;
|
||||
|
||||
extraStreamFlags#01 streamId:(## 8) flags:# enabled:flags.0?true dtx:flags.1?true extraEC:flags.2?true paused:flags.3?true = ExtraSignaling;
|
||||
extraStreamCsd#02 streamId:(## 8) width:(## 16) height:(## 16) count:(## 8) [ length:(## 8) codecSpecificData:bytes ]= ExtraSignaling;
|
||||
extraStreamFlags#01 flags:(## 8) enabled:flags.0?true dtx:flags.1?true extraEC:flags.2?true paused:flags.3?true = ExtraSignaling;
|
||||
extraStreamCsd#02 width:(## 16) height:(## 16) count:(## 8) [ length:(## 8) codecSpecificData:bytes ] = ExtraSignaling;
|
||||
|
||||
extraLanEndpoint#03 address:# port:(## 16) = ExtraSignaling;
|
||||
extraIpv6Endpoint#07 address:(## 128) port:(## 16) = ExtraSignaling;
|
||||
|
||||
extraNetworkChanged#04 flags:# dataSavingEnabled:flags.0?true = ExtraSignaling;
|
||||
extraNetworkChanged#04 flags:(## 8) dataSavingEnabled:flags.0?true = ExtraSignaling;
|
||||
|
||||
extraGroupCallKey#05 key:(## 256) = ExtraSignaling;
|
||||
extraGroupCallUpgrade#06 = ExtraSignaling;
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
uint32_t ReadTlLength() const;
|
||||
void ReadBytes(unsigned char *to, size_t count) const;
|
||||
void ReadBytes(Buffer &to) const;
|
||||
BufferInputStream GetPartBuffer(size_t length, bool advance) const;
|
||||
BufferInputStream GetPartBuffer(size_t length, bool advance = true) const;
|
||||
const unsigned char *GetRawBuffer() const;
|
||||
|
||||
inline uint64_t ReadUInt64() const
|
||||
@ -278,98 +278,6 @@ private:
|
||||
std::function<void *(void *, size_t)> reallocFn;
|
||||
};
|
||||
|
||||
template <typename T, size_t size, typename AVG_T = T>
|
||||
class HistoricBuffer
|
||||
{
|
||||
public:
|
||||
HistoricBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
AVG_T Average() const
|
||||
{
|
||||
return std::accumulate(data.begin(), data.end(), static_cast<AVG_T>(0)) / static_cast<AVG_T>(size);
|
||||
}
|
||||
|
||||
AVG_T Average(size_t firstN) const
|
||||
{
|
||||
AVG_T avg = static_cast<AVG_T>(0);
|
||||
for (size_t i = 0; i < firstN; i++) // Manual iteration required to wrap around array with specific offset
|
||||
{
|
||||
avg += (*this)[i];
|
||||
}
|
||||
return avg / static_cast<AVG_T>(firstN);
|
||||
}
|
||||
|
||||
AVG_T NonZeroAverage() const
|
||||
{
|
||||
AVG_T avg = static_cast<AVG_T>(0);
|
||||
int nonZeroCount = 0;
|
||||
for (T i : data)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
nonZeroCount++;
|
||||
avg += i;
|
||||
}
|
||||
}
|
||||
if (nonZeroCount == 0)
|
||||
return static_cast<AVG_T>(0);
|
||||
return avg / static_cast<AVG_T>(nonZeroCount);
|
||||
}
|
||||
|
||||
void Add(T el)
|
||||
{
|
||||
data[offset] = el;
|
||||
offset = (offset + 1) % size;
|
||||
}
|
||||
|
||||
T Min() const
|
||||
{
|
||||
return *std::min_element(data.begin(), data.end());
|
||||
}
|
||||
|
||||
T Max() const
|
||||
{
|
||||
return *std::max_element(data.begin(), data.end());
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
std::fill(data.begin(), data.end(), static_cast<T>(0));
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
T operator[](size_t i) const
|
||||
{
|
||||
assert(i < size);
|
||||
// [0] should return the most recent entry, [1] the one before it, and so on
|
||||
ptrdiff_t _i = offset - i - 1;
|
||||
if (_i < 0) // Wrap around offset a-la posmod
|
||||
_i = size + _i;
|
||||
return data[_i];
|
||||
}
|
||||
|
||||
T &operator[](size_t i)
|
||||
{
|
||||
assert(i < size);
|
||||
// [0] should return the most recent entry, [1] the one before it, and so on
|
||||
ptrdiff_t _i = offset - i - 1;
|
||||
if (_i < 0) // Wrap around offset a-la posmod
|
||||
_i = size + _i;
|
||||
return data[_i];
|
||||
}
|
||||
|
||||
constexpr size_t Size() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<T, size> data{};
|
||||
ptrdiff_t offset = 0;
|
||||
};
|
||||
|
||||
template <size_t bufSize, size_t bufCount>
|
||||
class BufferPool
|
||||
{
|
||||
|
@ -15,4 +15,94 @@ TGVOIP_DISALLOW_COPY_AND_ASSIGN(TypeName); \
|
||||
TypeName(TypeName&&) = default; \
|
||||
TypeName& operator=(TypeName&&) = default
|
||||
|
||||
template <typename T, size_t size, typename AVG_T = T>
|
||||
class HistoricBuffer
|
||||
{
|
||||
public:
|
||||
HistoricBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
AVG_T Average() const
|
||||
{
|
||||
return std::accumulate(data.begin(), data.end(), static_cast<AVG_T>(0)) / static_cast<AVG_T>(size);
|
||||
}
|
||||
|
||||
AVG_T Average(size_t firstN) const
|
||||
{
|
||||
AVG_T avg = static_cast<AVG_T>(0);
|
||||
for (size_t i = 0; i < firstN; i++) // Manual iteration required to wrap around array with specific offset
|
||||
{
|
||||
avg += (*this)[i];
|
||||
}
|
||||
return avg / static_cast<AVG_T>(firstN);
|
||||
}
|
||||
|
||||
AVG_T NonZeroAverage() const
|
||||
{
|
||||
AVG_T avg = static_cast<AVG_T>(0);
|
||||
int nonZeroCount = 0;
|
||||
for (T &i : data)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
nonZeroCount++;
|
||||
avg += i;
|
||||
}
|
||||
}
|
||||
if (nonZeroCount == 0)
|
||||
return static_cast<AVG_T>(0);
|
||||
return avg / static_cast<AVG_T>(nonZeroCount);
|
||||
}
|
||||
|
||||
void Add(T el)
|
||||
{
|
||||
data[offset] = el;
|
||||
offset = (offset + 1) % size;
|
||||
}
|
||||
|
||||
T Min() const
|
||||
{
|
||||
return *std::min_element(data.begin(), data.end());
|
||||
}
|
||||
|
||||
T Max() const
|
||||
{
|
||||
return *std::max_element(data.begin(), data.end());
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
std::fill(data.begin(), data.end(), static_cast<T>(0));
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
T operator[](size_t i) const
|
||||
{
|
||||
assert(i < size);
|
||||
// [0] should return the most recent entry, [1] the one before it, and so on
|
||||
ptrdiff_t _i = offset - i - 1;
|
||||
if (_i < 0) // Wrap around offset a-la posmod
|
||||
_i = size + _i;
|
||||
return data[_i];
|
||||
}
|
||||
|
||||
T &operator[](size_t i)
|
||||
{
|
||||
assert(i < size);
|
||||
// [0] should return the most recent entry, [1] the one before it, and so on
|
||||
ptrdiff_t _i = offset - i - 1;
|
||||
if (_i < 0) // Wrap around offset a-la posmod
|
||||
_i = size + _i;
|
||||
return data[_i];
|
||||
}
|
||||
|
||||
constexpr size_t Size() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<T, size> data{};
|
||||
ptrdiff_t offset = 0;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user