mirror of
https://github.com/danog/libtgvoip.git
synced 2024-12-02 09:37:52 +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/audio/AudioPacketSender.cpp \
|
||||||
controller/net/PacketReassembler.cpp \
|
controller/net/PacketReassembler.cpp \
|
||||||
controller/protocol/PacketManager.cpp \
|
controller/protocol/PacketManager.cpp \
|
||||||
|
controller/protocol/PacketStructs.cpp \
|
||||||
VoIPGroupController.cpp \
|
VoIPGroupController.cpp \
|
||||||
VoIPServerConfig.cpp \
|
VoIPServerConfig.cpp \
|
||||||
audio/AudioIO.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/OpusEncoder.cpp \
|
||||||
controller/audio/AudioPacketSender.cpp \
|
controller/audio/AudioPacketSender.cpp \
|
||||||
controller/net/PacketReassembler.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 \
|
VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \
|
||||||
audio/AudioOutput.cpp audio/Resampler.cpp \
|
audio/AudioOutput.cpp audio/Resampler.cpp \
|
||||||
audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.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/OpusEncoder.lo \
|
||||||
controller/audio/AudioPacketSender.lo \
|
controller/audio/AudioPacketSender.lo \
|
||||||
controller/net/PacketReassembler.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 \
|
VoIPServerConfig.lo audio/AudioIO.lo audio/AudioInput.lo \
|
||||||
audio/AudioOutput.lo audio/Resampler.lo \
|
audio/AudioOutput.lo audio/Resampler.lo \
|
||||||
audio/AudioInputTester.lo os/posix/NetworkSocketPosix.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)/NetworkSocket.Plo \
|
||||||
controller/net/$(DEPDIR)/PacketReassembler.Plo \
|
controller/net/$(DEPDIR)/PacketReassembler.Plo \
|
||||||
controller/protocol/$(DEPDIR)/PacketManager.Plo \
|
controller/protocol/$(DEPDIR)/PacketManager.Plo \
|
||||||
|
controller/protocol/$(DEPDIR)/PacketStructs.Plo \
|
||||||
os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo \
|
os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo \
|
||||||
os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo \
|
os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo \
|
||||||
os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo \
|
os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo \
|
||||||
@ -2393,7 +2396,8 @@ SRC = TgVoip.cpp VoIPController.cpp tools/Buffers.cpp \
|
|||||||
controller/audio/OpusEncoder.cpp \
|
controller/audio/OpusEncoder.cpp \
|
||||||
controller/audio/AudioPacketSender.cpp \
|
controller/audio/AudioPacketSender.cpp \
|
||||||
controller/net/PacketReassembler.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 \
|
VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \
|
||||||
audio/AudioOutput.cpp audio/Resampler.cpp \
|
audio/AudioOutput.cpp audio/Resampler.cpp \
|
||||||
audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \
|
audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \
|
||||||
@ -2571,6 +2575,9 @@ controller/protocol/$(DEPDIR)/$(am__dirstamp):
|
|||||||
controller/protocol/PacketManager.lo: \
|
controller/protocol/PacketManager.lo: \
|
||||||
controller/protocol/$(am__dirstamp) \
|
controller/protocol/$(am__dirstamp) \
|
||||||
controller/protocol/$(DEPDIR)/$(am__dirstamp)
|
controller/protocol/$(DEPDIR)/$(am__dirstamp)
|
||||||
|
controller/protocol/PacketStructs.lo: \
|
||||||
|
controller/protocol/$(am__dirstamp) \
|
||||||
|
controller/protocol/$(DEPDIR)/$(am__dirstamp)
|
||||||
audio/$(am__dirstamp):
|
audio/$(am__dirstamp):
|
||||||
@$(MKDIR_P) audio
|
@$(MKDIR_P) audio
|
||||||
@: > audio/$(am__dirstamp)
|
@: > 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)/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/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)/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)/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)/AudioInputAudioUnitOSX.Plo@am__quote@ # am--include-marker
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@os/darwin/$(DEPDIR)/AudioOutputAudioUnit.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)/NetworkSocket.Plo
|
||||||
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
||||||
-rm -f controller/protocol/$(DEPDIR)/PacketManager.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)/AudioInputAudioUnit.Plo
|
||||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
||||||
-rm -f os/darwin/$(DEPDIR)/AudioOutputAudioUnit.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)/NetworkSocket.Plo
|
||||||
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
-rm -f controller/net/$(DEPDIR)/PacketReassembler.Plo
|
||||||
-rm -f controller/protocol/$(DEPDIR)/PacketManager.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)/AudioInputAudioUnit.Plo
|
||||||
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
-rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnitOSX.Plo
|
||||||
-rm -f os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo
|
-rm -f os/darwin/$(DEPDIR)/AudioOutputAudioUnit.Plo
|
||||||
|
@ -62,7 +62,6 @@ enum ProtocolVersions
|
|||||||
// Extra packet flags
|
// Extra packet flags
|
||||||
#define XPFLAG_HAS_EXTRA 1 // Signaling
|
#define XPFLAG_HAS_EXTRA 1 // Signaling
|
||||||
#define XPFLAG_HAS_RECV_TS 2 // Video calls
|
#define XPFLAG_HAS_RECV_TS 2 // Video calls
|
||||||
#define XPFLAG_HAS_TRANSPORT_ID 4 // TODO: remove, not used
|
|
||||||
|
|
||||||
|
|
||||||
// Extra signaling packet types
|
// Extra signaling packet types
|
||||||
@ -74,6 +73,9 @@ enum ProtocolVersions
|
|||||||
#define EXTRA_TYPE_REQUEST_GROUP 6
|
#define EXTRA_TYPE_REQUEST_GROUP 6
|
||||||
#define EXTRA_TYPE_IPV6_ENDPOINT 7
|
#define EXTRA_TYPE_IPV6_ENDPOINT 7
|
||||||
|
|
||||||
|
#define EXTRA_TYPE_INIT 8
|
||||||
|
#define EXTRA_TYPE_INIT_ACK 9
|
||||||
|
|
||||||
// Stream signaling flags
|
// Stream signaling flags
|
||||||
#define STREAM_FLAG_ENABLED 1
|
#define STREAM_FLAG_ENABLED 1
|
||||||
#define STREAM_FLAG_DTX 2
|
#define STREAM_FLAG_DTX 2
|
||||||
|
@ -38,7 +38,7 @@ size_t VoIPController::decryptPacket(unsigned char *buffer, BufferInputStream &i
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(buffer + in.GetOffset(), aesOut, in.Remaining());
|
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->buffer = bufferPool.Get();
|
||||||
slot->recvTimeDiff = time - prevRecvTime;
|
slot->recvTimeDiff = time - prevRecvTime;
|
||||||
slot->isEC = pkt.isEC;
|
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
|
#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);
|
fprintf(dump, "%u\t%.03f\t%d\t%.03f\t%.03f\t%.03f\n", pkt.timestamp, time, GetCurrentDelay(), lastMeasuredJitter, lastMeasuredDelay, minDelay);
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,6 +204,13 @@ NetworkAddress NetworkAddress::IPv4(uint32_t addr)
|
|||||||
a.addr.ipv4 = addr;
|
a.addr.ipv4 = addr;
|
||||||
return a;
|
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)
|
NetworkAddress NetworkAddress::IPv6(std::string str)
|
||||||
{
|
{
|
||||||
@ -224,6 +231,13 @@ NetworkAddress NetworkAddress::IPv6(const uint8_t addr[16])
|
|||||||
memcpy(a.addr.ipv6, addr, 16);
|
memcpy(a.addr.ipv6, addr, 16);
|
||||||
return a;
|
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)
|
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 Empty();
|
||||||
static NetworkAddress IPv4(std::string str);
|
static NetworkAddress IPv4(std::string str);
|
||||||
static NetworkAddress IPv4(uint32_t addr);
|
static NetworkAddress IPv4(uint32_t addr);
|
||||||
|
static NetworkAddress IPv4(const BufferInputStream &in);
|
||||||
static NetworkAddress IPv6(std::string str);
|
static NetworkAddress IPv6(std::string str);
|
||||||
static NetworkAddress IPv6(const uint8_t addr[16]);
|
static NetworkAddress IPv6(const uint8_t addr[16]);
|
||||||
|
static NetworkAddress IPv6(const BufferInputStream &in);
|
||||||
|
|
||||||
bool isIPv6 = false;
|
bool isIPv6 = false;
|
||||||
union {
|
union {
|
||||||
|
@ -3,84 +3,6 @@
|
|||||||
using namespace tgvoip;
|
using namespace tgvoip;
|
||||||
using namespace std;
|
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)
|
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;
|
ENFORCE_MSG_THREAD;
|
||||||
|
|
||||||
LOGV("Sending extra type %u length %u", type, (unsigned int)data.Length());
|
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;
|
extra.firstContainingSeq = 0;
|
||||||
x->data = move(data);
|
extra.data = move(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnacknowledgedExtraData xd = {type, move(data), 0};
|
currentExtras.push_back(UnacknowledgedExtraData{type, move(data), 0});
|
||||||
currentExtras.push_back(move(xd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoIPController::SendUdpPing(Endpoint &endpoint)
|
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
|
namespace tgvoip
|
||||||
{
|
{
|
||||||
class PacketSender;
|
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 seq;
|
||||||
uint32_t ackSeq;
|
uint32_t ackSeq;
|
||||||
uint32_t ackMask;
|
uint32_t ackMask;
|
||||||
|
|
||||||
uint8_t streamId;
|
uint8_t streamId;
|
||||||
uint8_t flags;
|
uint8_t flags = 0;
|
||||||
|
uint8_t eFlags = 0;
|
||||||
|
|
||||||
|
uint32_t recvTS = 0;
|
||||||
|
|
||||||
Buffer data;
|
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
|
struct RecentOutgoingPacket
|
||||||
{
|
{
|
||||||
// For simple NACK reliable resending
|
// For simple NACK reliable resending
|
||||||
|
@ -906,10 +906,8 @@ void VoIPController::ProcessExtraData(Buffer &data)
|
|||||||
{
|
{
|
||||||
if (!allowP2p)
|
if (!allowP2p)
|
||||||
return;
|
return;
|
||||||
unsigned char _addr[16];
|
NetworkAddress addr = NetworkAddress::IPv6(in);
|
||||||
in.ReadBytes(_addr, 16);
|
uint16_t port = in.ReadUInt16();
|
||||||
NetworkAddress addr = NetworkAddress::IPv6(_addr);
|
|
||||||
uint16_t port = static_cast<uint16_t>(in.ReadInt16());
|
|
||||||
peerIPv6Available = true;
|
peerIPv6Available = true;
|
||||||
LOGV("Received peer IPv6 endpoint [%s]:%u", addr.ToString().c_str(), port);
|
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);
|
s.WriteByte(flags);
|
||||||
|
|
||||||
if (flags & XPFLAG_HAS_TRANSPORT_ID)
|
|
||||||
{
|
|
||||||
s.WriteByte(manager.getTransportId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentExtras.empty())
|
if (!currentExtras.empty())
|
||||||
{
|
{
|
||||||
s.WriteByte(static_cast<unsigned char>(currentExtras.size()));
|
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;
|
streamInfo$_ streamId:(## 8) type:(## 8) codec:# frameDurationIgnored:(## 16) enabled:(## 8)= StreamInfo;
|
||||||
|
|
||||||
// Packet
|
// 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;
|
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;
|
payloadInitAck#1 peerVersion:# minVersion:# streams:Extras<StreamInfo> = Payload;
|
||||||
|
@ -23,6 +23,7 @@ packet$_
|
|||||||
|
|
||||||
extraFEC:flags.1?ExtraFEC
|
extraFEC:flags.1?ExtraFEC
|
||||||
extraSignaling:flags.2?Extras<ExtraSignaling>
|
extraSignaling:flags.2?Extras<ExtraSignaling>
|
||||||
|
recvTS:flags.3?int
|
||||||
|
|
||||||
= Packet;
|
= Packet;
|
||||||
|
|
||||||
@ -32,13 +33,13 @@ extraFEC$_ mask:(## 8) [ length:(## 8) _:bytes ] = ExtraFEC;
|
|||||||
// Extras
|
// Extras
|
||||||
extras$_ {t:Type} (## 8) [ length:(## 8) extra:t ] = Extras t;
|
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;
|
extraStreamFlags#01 flags:(## 8) 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;
|
extraStreamCsd#02 width:(## 16) height:(## 16) count:(## 8) [ length:(## 8) codecSpecificData:bytes ] = ExtraSignaling;
|
||||||
|
|
||||||
extraLanEndpoint#03 address:# port:(## 16) = ExtraSignaling;
|
extraLanEndpoint#03 address:# port:(## 16) = ExtraSignaling;
|
||||||
extraIpv6Endpoint#07 address:(## 128) 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;
|
extraGroupCallKey#05 key:(## 256) = ExtraSignaling;
|
||||||
extraGroupCallUpgrade#06 = ExtraSignaling;
|
extraGroupCallUpgrade#06 = ExtraSignaling;
|
||||||
|
@ -44,7 +44,7 @@ public:
|
|||||||
uint32_t ReadTlLength() const;
|
uint32_t ReadTlLength() const;
|
||||||
void ReadBytes(unsigned char *to, size_t count) const;
|
void ReadBytes(unsigned char *to, size_t count) const;
|
||||||
void ReadBytes(Buffer &to) 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;
|
const unsigned char *GetRawBuffer() const;
|
||||||
|
|
||||||
inline uint64_t ReadUInt64() const
|
inline uint64_t ReadUInt64() const
|
||||||
@ -278,98 +278,6 @@ private:
|
|||||||
std::function<void *(void *, size_t)> reallocFn;
|
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>
|
template <size_t bufSize, size_t bufCount>
|
||||||
class BufferPool
|
class BufferPool
|
||||||
{
|
{
|
||||||
|
@ -15,4 +15,94 @@ TGVOIP_DISALLOW_COPY_AND_ASSIGN(TypeName); \
|
|||||||
TypeName(TypeName&&) = default; \
|
TypeName(TypeName&&) = default; \
|
||||||
TypeName& operator=(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