From 16ff209ff7244dc62c7fdc98d18df33b8a0b5b63 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Tue, 17 Mar 2020 20:11:27 +0100 Subject: [PATCH] Begin refactoring protocol structures --- Makefile.am | 1 + Makefile.in | 16 ++- controller/PrivateDefines.h | 4 +- controller/controller/Crypto.cpp | 2 +- controller/net/JitterBuffer.cpp | 2 +- controller/net/NetworkSocket.cpp | 14 ++ controller/net/NetworkSocket.h | 2 + controller/protocol/Legacy.cpp | 78 ----------- controller/protocol/NetworkAPI.cpp | 11 +- controller/protocol/PacketStructs.cpp | 183 ++++++++++++++++++++++++ controller/protocol/PacketStructs.h | 195 +++++++++++++++++++++++++- controller/protocol/Protocol.cpp | 11 +- scheme.tlb | 2 +- schemeNew.tlb | 7 +- tools/Buffers.h | 94 +------------ tools/utils.h | 90 ++++++++++++ 16 files changed, 513 insertions(+), 199 deletions(-) create mode 100644 controller/protocol/PacketStructs.cpp diff --git a/Makefile.am b/Makefile.am index 96c0fea..2d7575d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/Makefile.in b/Makefile.in index 6e3cf99..ffcfe8f 100644 --- a/Makefile.in +++ b/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 diff --git a/controller/PrivateDefines.h b/controller/PrivateDefines.h index 796f352..2a25533 100644 --- a/controller/PrivateDefines.h +++ b/controller/PrivateDefines.h @@ -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 diff --git a/controller/controller/Crypto.cpp b/controller/controller/Crypto.cpp index 9f49269..3dcbab5 100644 --- a/controller/controller/Crypto.cpp +++ b/controller/controller/Crypto.cpp @@ -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(); } } diff --git a/controller/net/JitterBuffer.cpp b/controller/net/JitterBuffer.cpp index 3f4176e..3951dc5 100755 --- a/controller/net/JitterBuffer.cpp +++ b/controller/net/JitterBuffer.cpp @@ -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 diff --git a/controller/net/NetworkSocket.cpp b/controller/net/NetworkSocket.cpp index 41e2216..7a8e588 100644 --- a/controller/net/NetworkSocket.cpp +++ b/controller/net/NetworkSocket.cpp @@ -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> &readFds, std::vector> &writeFds, std::vector> &errorFds, const std::unique_ptr &canceller) { diff --git a/controller/net/NetworkSocket.h b/controller/net/NetworkSocket.h index c1a8079..4e39e5a 100644 --- a/controller/net/NetworkSocket.h +++ b/controller/net/NetworkSocket.h @@ -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 { diff --git a/controller/protocol/Legacy.cpp b/controller/protocol/Legacy.cpp index b1272eb..b6c175c 100644 --- a/controller/protocol/Legacy.cpp +++ b/controller/protocol/Legacy.cpp @@ -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) { diff --git a/controller/protocol/NetworkAPI.cpp b/controller/protocol/NetworkAPI.cpp index e2325ed..2bf241a 100644 --- a/controller/protocol/NetworkAPI.cpp +++ b/controller/protocol/NetworkAPI.cpp @@ -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::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) diff --git a/controller/protocol/PacketStructs.cpp b/controller/protocol/PacketStructs.cpp new file mode 100644 index 0000000..4aa113d --- /dev/null +++ b/controller/protocol/PacketStructs.cpp @@ -0,0 +1,183 @@ +#include "PacketStructs.h" +#include "../PrivateDefines.cpp" + +using namespace tgvoip; + +std::shared_ptr choose(const BufferInputStream &in, int peerVersion) +{ + switch (in.ReadByte()) + { + case ExtraStreamFlags::ID: + return std::make_shared(); + case ExtraStreamCsd::ID: + return std::make_shared(); + case ExtraLanEndpoint::ID: + return std::make_shared(); + case ExtraIpv6Endpoint::ID: + return std::make_shared(); + case ExtraNetworkChanged::ID: + return std::make_shared(); + case ExtraGroupCallKey::ID: + return std::make_shared(); + case ExtraGroupCallUpgrade::ID: + return std::make_shared(); + } +} + +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; +} \ No newline at end of file diff --git a/controller/protocol/PacketStructs.h b/controller/protocol/PacketStructs.h index 226326e..223fb36 100644 --- a/controller/protocol/PacketStructs.h +++ b/controller/protocol/PacketStructs.h @@ -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 +struct Array +{ +public: + bool parse(const BufferInputStream &in, int peerVersion) override; + bool serialize(BufferOutputStream &out, int peerVersion) override; + + std::vector> contents; +}; + +struct Extra : public Serializable +{ + static std::shared_ptr 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> extras; }; + +struct StreamInfo : public Serializable +{ +public: + static std::shared_ptr choose(const BufferInputStream &in, int peerVersion) + { + return std::make_shared(); + }; + + 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 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 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> 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> streams; + + static const uint8_t ID = 8; +}; + +// Legacy stuff struct RecentOutgoingPacket { // For simple NACK reliable resending diff --git a/controller/protocol/Protocol.cpp b/controller/protocol/Protocol.cpp index c0dfb05..e666738 100644 --- a/controller/protocol/Protocol.cpp +++ b/controller/protocol/Protocol.cpp @@ -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(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(currentExtras.size())); diff --git a/scheme.tlb b/scheme.tlb index 03a5f55..ec7c06f 100644 --- a/scheme.tlb +++ b/scheme.tlb @@ -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 data:payload = Packet; +packet$_ type:(## 8) ackSeq:# seq:# ackMask:# flags:(## 8) extras:flags.0?Extras recvTS:flags.1?int data:payload = Packet; payloadInit#0 peerVersion:# minVersion:# flags:# streams:Extras dataSavingEnabled:flags.0?true groupCallSupported:flags.1?true videoSendSupported:flags.2?true videoRecvSupported:flags.3?true = Payload; payloadInitAck#1 peerVersion:# minVersion:# streams:Extras = Payload; diff --git a/schemeNew.tlb b/schemeNew.tlb index bea8647..4efe29e 100644 --- a/schemeNew.tlb +++ b/schemeNew.tlb @@ -23,6 +23,7 @@ packet$_ extraFEC:flags.1?ExtraFEC extraSignaling:flags.2?Extras + 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; diff --git a/tools/Buffers.h b/tools/Buffers.h index 0a171b9..cd26b92 100644 --- a/tools/Buffers.h +++ b/tools/Buffers.h @@ -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 reallocFn; }; -template -class HistoricBuffer -{ -public: - HistoricBuffer() - { - } - - AVG_T Average() const - { - return std::accumulate(data.begin(), data.end(), static_cast(0)) / static_cast(size); - } - - AVG_T Average(size_t firstN) const - { - AVG_T avg = static_cast(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(firstN); - } - - AVG_T NonZeroAverage() const - { - AVG_T avg = static_cast(0); - int nonZeroCount = 0; - for (T i : data) - { - if (i != 0) - { - nonZeroCount++; - avg += i; - } - } - if (nonZeroCount == 0) - return static_cast(0); - return avg / static_cast(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(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 data{}; - ptrdiff_t offset = 0; -}; - template class BufferPool { diff --git a/tools/utils.h b/tools/utils.h index 3f905a9..9fa2102 100644 --- a/tools/utils.h +++ b/tools/utils.h @@ -15,4 +15,94 @@ TGVOIP_DISALLOW_COPY_AND_ASSIGN(TypeName); \ TypeName(TypeName&&) = default; \ TypeName& operator=(TypeName&&) = default +template +class HistoricBuffer +{ +public: + HistoricBuffer() + { + } + AVG_T Average() const + { + return std::accumulate(data.begin(), data.end(), static_cast(0)) / static_cast(size); + } + + AVG_T Average(size_t firstN) const + { + AVG_T avg = static_cast(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(firstN); + } + + AVG_T NonZeroAverage() const + { + AVG_T avg = static_cast(0); + int nonZeroCount = 0; + for (T &i : data) + { + if (i != 0) + { + nonZeroCount++; + avg += i; + } + } + if (nonZeroCount == 0) + return static_cast(0); + return avg / static_cast(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(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 data{}; + ptrdiff_t offset = 0; +};