diff --git a/.gitignore b/.gitignore index 100a3bc..8cabb89 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ autom4te.cache/ *.o *.Plo *.lo +.vscode diff --git a/Makefile.am b/Makefile.am index 7ee66a3..09396c5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,7 @@ tools/logging.cpp \ controller/MediaStreamItf.cpp \ tools/MessageThread.cpp \ controller/net/NetworkSocket.cpp \ +controller/net/Endpoint.cpp \ controller/audio/OpusDecoder.cpp \ controller/audio/OpusEncoder.cpp \ controller/PacketReassembler.cpp \ @@ -23,6 +24,7 @@ audio/AudioIO.cpp \ audio/AudioInput.cpp \ audio/AudioOutput.cpp \ audio/Resampler.cpp \ +audio/AudioInputTester.cpp \ os/posix/NetworkSocketPosix.cpp \ video/VideoSource.cpp \ video/VideoRenderer.cpp \ @@ -763,4 +765,4 @@ CXXFLAGS += -std=gnu++0x $(CFLAGS) if TARGET_OS_OSX OBJCFLAGS = $(CFLAGS) OBJCXXFLAGS += -std=gnu++0x $(CFLAGS) -endif \ No newline at end of file +endif diff --git a/Makefile.in b/Makefile.in index 7a96955..0e799aa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -813,16 +813,17 @@ am__libtgvoip_la_SOURCES_DIST = TgVoip.cpp VoIPController.cpp \ controller/audio/EchoCanceller.cpp \ controller/net/JitterBuffer.cpp tools/logging.cpp \ controller/MediaStreamItf.cpp tools/MessageThread.cpp \ - controller/net/NetworkSocket.cpp \ + controller/net/NetworkSocket.cpp controller/net/Endpoint.cpp \ controller/audio/OpusDecoder.cpp \ controller/audio/OpusEncoder.cpp \ controller/PacketReassembler.cpp VoIPGroupController.cpp \ VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \ audio/AudioOutput.cpp audio/Resampler.cpp \ - os/posix/NetworkSocketPosix.cpp video/VideoSource.cpp \ - video/VideoRenderer.cpp video/VideoPacketSender.cpp \ - video/VideoFEC.cpp video/ScreamCongestionController.cpp \ - tools/json11.cpp os/darwin/AudioInputAudioUnit.cpp \ + audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \ + video/VideoSource.cpp video/VideoRenderer.cpp \ + video/VideoPacketSender.cpp video/VideoFEC.cpp \ + video/ScreamCongestionController.cpp tools/json11.cpp \ + os/darwin/AudioInputAudioUnit.cpp \ os/darwin/AudioOutputAudioUnit.cpp os/darwin/AudioUnitIO.cpp \ os/darwin/AudioInputAudioUnitOSX.cpp \ os/darwin/AudioOutputAudioUnitOSX.cpp \ @@ -1750,19 +1751,20 @@ am__objects_12 = TgVoip.lo VoIPController.lo tools/Buffers.lo \ controller/audio/EchoCanceller.lo \ controller/net/JitterBuffer.lo tools/logging.lo \ controller/MediaStreamItf.lo tools/MessageThread.lo \ - controller/net/NetworkSocket.lo \ + controller/net/NetworkSocket.lo controller/net/Endpoint.lo \ controller/audio/OpusDecoder.lo \ controller/audio/OpusEncoder.lo \ controller/PacketReassembler.lo VoIPGroupController.lo \ VoIPServerConfig.lo audio/AudioIO.lo audio/AudioInput.lo \ audio/AudioOutput.lo audio/Resampler.lo \ - os/posix/NetworkSocketPosix.lo video/VideoSource.lo \ - video/VideoRenderer.lo video/VideoPacketSender.lo \ - video/VideoFEC.lo video/ScreamCongestionController.lo \ - tools/json11.lo $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) $(am__objects_4) $(am__objects_5) \ - $(am__objects_6) $(am__objects_7) $(am__objects_8) \ - $(am__objects_9) $(am__objects_10) $(am__objects_11) + audio/AudioInputTester.lo os/posix/NetworkSocketPosix.lo \ + video/VideoSource.lo video/VideoRenderer.lo \ + video/VideoPacketSender.lo video/VideoFEC.lo \ + video/ScreamCongestionController.lo tools/json11.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) $(am__objects_8) $(am__objects_9) \ + $(am__objects_10) $(am__objects_11) am__objects_13 = $(am__objects_11) $(am__objects_11) $(am__objects_11) \ $(am__objects_11) am_libtgvoip_la_OBJECTS = $(am__objects_12) $(am__objects_13) @@ -2055,14 +2057,16 @@ am__depfiles_remade = ./$(DEPDIR)/TgVoip.Plo \ ./webrtc_dsp/third_party/rnnoise/src/$(DEPDIR)/rnn_vad_weights.Plo \ audio/$(DEPDIR)/AudioIO.Plo \ audio/$(DEPDIR)/AudioIOCallback.Plo \ - audio/$(DEPDIR)/AudioInput.Plo audio/$(DEPDIR)/AudioOutput.Plo \ - audio/$(DEPDIR)/Resampler.Plo \ + audio/$(DEPDIR)/AudioInput.Plo \ + audio/$(DEPDIR)/AudioInputTester.Plo \ + audio/$(DEPDIR)/AudioOutput.Plo audio/$(DEPDIR)/Resampler.Plo \ controller/$(DEPDIR)/MediaStreamItf.Plo \ controller/$(DEPDIR)/PacketReassembler.Plo \ controller/audio/$(DEPDIR)/EchoCanceller.Plo \ controller/audio/$(DEPDIR)/OpusDecoder.Plo \ controller/audio/$(DEPDIR)/OpusEncoder.Plo \ controller/net/$(DEPDIR)/CongestionControl.Plo \ + controller/net/$(DEPDIR)/Endpoint.Plo \ controller/net/$(DEPDIR)/JitterBuffer.Plo \ controller/net/$(DEPDIR)/NetworkSocket.Plo \ os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo \ @@ -2376,19 +2380,20 @@ SRC = TgVoip.cpp VoIPController.cpp tools/Buffers.cpp \ controller/audio/EchoCanceller.cpp \ controller/net/JitterBuffer.cpp tools/logging.cpp \ controller/MediaStreamItf.cpp tools/MessageThread.cpp \ - controller/net/NetworkSocket.cpp \ + controller/net/NetworkSocket.cpp controller/net/Endpoint.cpp \ controller/audio/OpusDecoder.cpp \ controller/audio/OpusEncoder.cpp \ controller/PacketReassembler.cpp VoIPGroupController.cpp \ VoIPServerConfig.cpp audio/AudioIO.cpp audio/AudioInput.cpp \ audio/AudioOutput.cpp audio/Resampler.cpp \ - os/posix/NetworkSocketPosix.cpp video/VideoSource.cpp \ - video/VideoRenderer.cpp video/VideoPacketSender.cpp \ - video/VideoFEC.cpp video/ScreamCongestionController.cpp \ - tools/json11.cpp $(am__append_1) $(am__append_4) \ - $(am__append_6) $(am__append_10) $(am__append_12) \ - $(am__append_14) $(am__append_16) $(am__append_18) \ - $(am__append_21) $(am__append_22) $(am__append_23) + audio/AudioInputTester.cpp os/posix/NetworkSocketPosix.cpp \ + video/VideoSource.cpp video/VideoRenderer.cpp \ + video/VideoPacketSender.cpp video/VideoFEC.cpp \ + video/ScreamCongestionController.cpp tools/json11.cpp \ + $(am__append_1) $(am__append_4) $(am__append_6) \ + $(am__append_10) $(am__append_12) $(am__append_14) \ + $(am__append_16) $(am__append_18) $(am__append_21) \ + $(am__append_22) $(am__append_23) TGVOIP_HDRS = TgVoip.h VoIPController.h tools/Buffers.h \ tools/BlockingQueue.h controller/PrivateDefines.h \ controller/net/CongestionControl.h \ @@ -2535,6 +2540,8 @@ tools/MessageThread.lo: tools/$(am__dirstamp) \ tools/$(DEPDIR)/$(am__dirstamp) controller/net/NetworkSocket.lo: controller/net/$(am__dirstamp) \ controller/net/$(DEPDIR)/$(am__dirstamp) +controller/net/Endpoint.lo: controller/net/$(am__dirstamp) \ + controller/net/$(DEPDIR)/$(am__dirstamp) controller/audio/OpusDecoder.lo: controller/audio/$(am__dirstamp) \ controller/audio/$(DEPDIR)/$(am__dirstamp) controller/audio/OpusEncoder.lo: controller/audio/$(am__dirstamp) \ @@ -2555,6 +2562,8 @@ audio/AudioOutput.lo: audio/$(am__dirstamp) \ audio/$(DEPDIR)/$(am__dirstamp) audio/Resampler.lo: audio/$(am__dirstamp) \ audio/$(DEPDIR)/$(am__dirstamp) +audio/AudioInputTester.lo: audio/$(am__dirstamp) \ + audio/$(DEPDIR)/$(am__dirstamp) os/posix/$(am__dirstamp): @$(MKDIR_P) os/posix @: > os/posix/$(am__dirstamp) @@ -3991,6 +4000,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/AudioIO.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/AudioIOCallback.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/AudioInput.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/AudioInputTester.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/AudioOutput.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@audio/$(DEPDIR)/Resampler.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@controller/$(DEPDIR)/MediaStreamItf.Plo@am__quote@ # am--include-marker @@ -3999,6 +4009,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@controller/audio/$(DEPDIR)/OpusDecoder.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@controller/audio/$(DEPDIR)/OpusEncoder.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@controller/net/$(DEPDIR)/CongestionControl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@controller/net/$(DEPDIR)/Endpoint.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@controller/net/$(DEPDIR)/JitterBuffer.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@os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo@am__quote@ # am--include-marker @@ -4874,6 +4885,7 @@ distclean: distclean-am -rm -f audio/$(DEPDIR)/AudioIO.Plo -rm -f audio/$(DEPDIR)/AudioIOCallback.Plo -rm -f audio/$(DEPDIR)/AudioInput.Plo + -rm -f audio/$(DEPDIR)/AudioInputTester.Plo -rm -f audio/$(DEPDIR)/AudioOutput.Plo -rm -f audio/$(DEPDIR)/Resampler.Plo -rm -f controller/$(DEPDIR)/MediaStreamItf.Plo @@ -4882,6 +4894,7 @@ distclean: distclean-am -rm -f controller/audio/$(DEPDIR)/OpusDecoder.Plo -rm -f controller/audio/$(DEPDIR)/OpusEncoder.Plo -rm -f controller/net/$(DEPDIR)/CongestionControl.Plo + -rm -f controller/net/$(DEPDIR)/Endpoint.Plo -rm -f controller/net/$(DEPDIR)/JitterBuffer.Plo -rm -f controller/net/$(DEPDIR)/NetworkSocket.Plo -rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo @@ -5240,6 +5253,7 @@ maintainer-clean: maintainer-clean-am -rm -f audio/$(DEPDIR)/AudioIO.Plo -rm -f audio/$(DEPDIR)/AudioIOCallback.Plo -rm -f audio/$(DEPDIR)/AudioInput.Plo + -rm -f audio/$(DEPDIR)/AudioInputTester.Plo -rm -f audio/$(DEPDIR)/AudioOutput.Plo -rm -f audio/$(DEPDIR)/Resampler.Plo -rm -f controller/$(DEPDIR)/MediaStreamItf.Plo @@ -5248,6 +5262,7 @@ maintainer-clean: maintainer-clean-am -rm -f controller/audio/$(DEPDIR)/OpusDecoder.Plo -rm -f controller/audio/$(DEPDIR)/OpusEncoder.Plo -rm -f controller/net/$(DEPDIR)/CongestionControl.Plo + -rm -f controller/net/$(DEPDIR)/Endpoint.Plo -rm -f controller/net/$(DEPDIR)/JitterBuffer.Plo -rm -f controller/net/$(DEPDIR)/NetworkSocket.Plo -rm -f os/darwin/$(DEPDIR)/AudioInputAudioUnit.Plo diff --git a/VoIPController.cpp b/VoIPController.cpp index f1c0370..07cb0b3 100644 --- a/VoIPController.cpp +++ b/VoIPController.cpp @@ -19,6 +19,7 @@ #include "controller/audio/OpusDecoder.h" #include "VoIPServerConfig.h" #include "controller/PrivateDefines.h" +#include "controller/net/Endpoint.h" #include "tools/json11.hpp" #include "controller/PacketSender.h" #include "video/VideoPacketSender.h" @@ -425,7 +426,7 @@ void VoIPController::SetNetworkType(int type) if (_preferredRelay.type == Endpoint::Type::UDP_RELAY) currentEndpoint = preferredRelay; MutexGuard m(endpointsMutex); - constexpr int64_t lanID = (int64_t)(FOURCC('L', 'A', 'N', '4')) << 32; + constexpr int64_t lanID = static_cast(FOURCC('L', 'A', 'N', '4')) << 32; endpoints.erase(lanID); for (pair &e : endpoints) { @@ -2095,9 +2096,9 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE size_t len = packet.data.Length(); BufferInputStream in(packet.data); bool hasPeerTag = false; - if (peerVersion < 9 || srcEndpoint.type == Endpoint::Type::UDP_RELAY || srcEndpoint.type == Endpoint::Type::TCP_RELAY) + if (peerVersion < 9 || srcEndpoint.IsReflector()) { - if (memcmp(buffer, srcEndpoint.type == Endpoint::Type::UDP_RELAY || srcEndpoint.type == Endpoint::Type::TCP_RELAY ? (void *)srcEndpoint.peerTag : (void *)callID, 16) != 0) + if (memcmp(buffer, srcEndpoint.IsReflector() ? (void *)srcEndpoint.peerTag : (void *)callID, 16) != 0) { LOGW("Received packet has wrong peerTag"); return; @@ -2105,7 +2106,7 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE in.Seek(16); hasPeerTag = true; } - if (in.Remaining() >= 16 && (srcEndpoint.type == Endpoint::Type::UDP_RELAY || srcEndpoint.type == Endpoint::Type::TCP_RELAY) && *reinterpret_cast(buffer + 16) == 0xFFFFFFFFFFFFFFFFLL && *reinterpret_cast(buffer + 24) == 0xFFFFFFFF) + if (in.Remaining() >= 16 && srcEndpoint.IsReflector() && *reinterpret_cast(buffer + 16) == 0xFFFFFFFFFFFFFFFFLL && *reinterpret_cast(buffer + 24) == 0xFFFFFFFF) { // relay special request response in.Seek(16 + 12); @@ -2160,8 +2161,8 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE uint32_t peerAddr = (uint32_t)in.ReadInt32(); uint32_t peerPort = (uint32_t)in.ReadInt32(); - constexpr int64_t p2pID = (int64_t)(FOURCC('P', '2', 'P', '4')) << 32; - constexpr int64_t lanID = (int64_t)(FOURCC('L', 'A', 'N', '4')) << 32; + constexpr int64_t p2pID = static_cast(FOURCC('P', '2', 'P', '4')) << 32; + constexpr int64_t lanID = static_cast(FOURCC('L', 'A', 'N', '4')) << 32; if (currentEndpoint == p2pID || currentEndpoint == lanID) currentEndpoint = preferredRelay; @@ -2583,7 +2584,7 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE } Endpoint *_currentEndpoint = &endpoints.at(currentEndpoint); - if (srcEndpoint.id != currentEndpoint && (srcEndpoint.type == Endpoint::Type::UDP_RELAY || srcEndpoint.type == Endpoint::Type::TCP_RELAY) && ((_currentEndpoint->type != Endpoint::Type::UDP_RELAY && _currentEndpoint->type != Endpoint::Type::TCP_RELAY) || _currentEndpoint->averageRTT == 0)) + if (srcEndpoint.id != currentEndpoint && srcEndpoint.IsReflector() && ((_currentEndpoint->type != Endpoint::Type::UDP_RELAY && _currentEndpoint->type != Endpoint::Type::TCP_RELAY) || _currentEndpoint->averageRTT == 0)) { if (seqgt(lastSentSeq - 32, lastRemoteAckSeq)) { @@ -3034,7 +3035,7 @@ void VoIPController::ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcE LOGV("received lan endpoint"); uint32_t peerAddr = (uint32_t)in.ReadInt32(); uint16_t peerPort = (uint16_t)in.ReadInt32(); - constexpr int64_t lanID = (int64_t)(FOURCC('L', 'A', 'N', '4')) << 32; + constexpr int64_t lanID = static_cast(FOURCC('L', 'A', 'N', '4')) << 32; unsigned char peerTag[16]; Endpoint lan(lanID, peerPort, NetworkAddress::IPv4(peerAddr), NetworkAddress::Empty(), Endpoint::Type::UDP_P2P_LAN, peerTag); @@ -3209,7 +3210,7 @@ void VoIPController::ProcessExtraData(Buffer &data) LOGV("received lan endpoint (extra)"); uint32_t peerAddr = (uint32_t)in.ReadInt32(); uint16_t peerPort = (uint16_t)in.ReadInt32(); - constexpr int64_t lanID = (int64_t)(FOURCC('L', 'A', 'N', '4')) << 32; + constexpr int64_t lanID = static_cast(FOURCC('L', 'A', 'N', '4')) << 32; if (currentEndpoint == lanID) currentEndpoint = preferredRelay; @@ -3268,7 +3269,7 @@ void VoIPController::ProcessExtraData(Buffer &data) peerIPv6Available = true; LOGV("Received peer IPv6 endpoint [%s]:%u", addr.ToString().c_str(), port); - constexpr int64_t p2pID = (int64_t)(FOURCC('P', '2', 'P', '6')) << 32; + constexpr int64_t p2pID = static_cast(FOURCC('P', '2', 'P', '6')) << 32; Endpoint ep; ep.type = Endpoint::Type::UDP_P2P_INET; @@ -3390,7 +3391,7 @@ void VoIPController::SendPacket(unsigned char *data, size_t len, Endpoint &ep, P if (ep.type == Endpoint::Type::TCP_RELAY && !useTCP) return; BufferOutputStream out(len + 128); - if (ep.type == Endpoint::Type::UDP_RELAY || ep.type == Endpoint::Type::TCP_RELAY) + if (ep.IsReflector()) out.WriteBytes((unsigned char *)ep.peerTag, 16); else if (peerVersion < 9) out.WriteBytes(callID, 16); @@ -3465,19 +3466,14 @@ void VoIPController::SendPacket(unsigned char *data, size_t len, Endpoint &ep, P LOGV("Sending: to=%s:%u, seq=%u, length=%u, type=%s", ep.GetAddress().ToString().c_str(), ep.port, srcPacket.seq, (unsigned int)out.GetLength(), GetPacketTypeString(srcPacket.type).c_str()); #endif - /*ActuallySendPacket(NetworkPacket{ - Buffer(std::move(out)), - ep.GetAddress(), - ep.port, - ep.type==Endpoint::Type::TCP_RELAY ? NetworkProtocol::TCP : NetworkProtocol::UDP - }, ep);*/ - rawSendQueue.Put(RawPendingOutgoingPacket{ - NetworkPacket{ - Buffer(std::move(out)), - ep.GetAddress(), - ep.port, - ep.type == Endpoint::Type::TCP_RELAY ? NetworkProtocol::TCP : NetworkProtocol::UDP}, - ep.type == Endpoint::Type::TCP_RELAY ? ep.socket : nullptr}); + rawSendQueue.Put( + RawPendingOutgoingPacket{ + NetworkPacket{ + Buffer(std::move(out)), + ep.GetAddress(), + ep.port, + ep.type == Endpoint::Type::TCP_RELAY ? NetworkProtocol::TCP : NetworkProtocol::UDP}, + ep.type == Endpoint::Type::TCP_RELAY ? ep.socket : nullptr}); } void VoIPController::ActuallySendPacket(NetworkPacket pkt, Endpoint &ep) @@ -3556,21 +3552,18 @@ std::string VoIPController::GetPacketTypeString(unsigned char type) case PKT_STREAM_EC: return "stream_ec"; } - char buf[255]; - snprintf(buf, sizeof(buf), "unknown(%u)", type); - return string(buf); + return string("unknown(") + std::to_string(type) + ')'; } void VoIPController::AddIPv6Relays() { - if (!myIPv6.IsEmpty() && !didAddIPv6Relays) { unordered_map> endpointsByAddress; for (pair &_e : endpoints) { Endpoint &e = _e.second; - if ((e.type == Endpoint::Type::UDP_RELAY || e.type == Endpoint::Type::TCP_RELAY) && !e.v6address.IsEmpty() && !e.address.IsEmpty()) + if ((e.IsReflector()) && !e.v6address.IsEmpty() && !e.address.IsEmpty()) { endpointsByAddress[e.v6address.ToString()].push_back(e); } @@ -3582,7 +3575,7 @@ void VoIPController::AddIPv6Relays() { didAddIPv6Relays = true; e.address = NetworkAddress::Empty(); - e.id = e.id ^ ((int64_t)(FOURCC('I', 'P', 'v', '6')) << 32); + e.id = e.id ^ (static_cast(FOURCC('I', 'P', 'v', '6')) << 32); e.averageRTT = 0; e.lastPingSeq = 0; e.lastPingTime = 0; @@ -3621,7 +3614,7 @@ void VoIPController::AddTCPRelays() tcpRelay.lastPingTime = 0; tcpRelay.rtts.Reset(); tcpRelay.udpPongCount = 0; - tcpRelay.id = tcpRelay.id ^ ((int64_t)(FOURCC('T', 'C', 'P', 0)) << 32); + tcpRelay.id = tcpRelay.id ^ (static_cast(FOURCC('T', 'C', 'P', 0)) << 32); if (setCurrentEndpointToTCP && endpoints.at(currentEndpoint).type != Endpoint::Type::TCP_RELAY) { LOGV("Setting current endpoint to TCP"); @@ -3750,7 +3743,7 @@ void VoIPController::SendPublicEndpointsRequest(const Endpoint &relay) NetworkProtocol::UDP}); } -Endpoint &VoIPController::GetEndpointByType(int type) +Endpoint &VoIPController::GetEndpointByType(const Endpoint::Type type) { if (type == Endpoint::Type::UDP_RELAY && preferredRelay) return endpoints.at(preferredRelay); @@ -4168,7 +4161,7 @@ void VoIPController::SendRelayPings() preferredRelay = minPingRelay->id; _preferredRelay = minPingRelay; LOGV("set preferred relay to %s", _preferredRelay->address.ToString().c_str()); - if (_currentEndpoint->type == Endpoint::Type::UDP_RELAY || _currentEndpoint->type == Endpoint::Type::TCP_RELAY) + if (_currentEndpoint->IsReflector()) { currentEndpoint = preferredRelay; _currentEndpoint = _preferredRelay; @@ -4176,8 +4169,8 @@ void VoIPController::SendRelayPings() } if (_currentEndpoint->type == Endpoint::Type::UDP_RELAY && useUDP) { - constexpr int64_t p2pID = (int64_t)(FOURCC('P', '2', 'P', '4')) << 32; - constexpr int64_t lanID = (int64_t)(FOURCC('L', 'A', 'N', '4')) << 32; + constexpr int64_t p2pID = static_cast(FOURCC('P', '2', 'P', '4')) << 32; + constexpr int64_t lanID = static_cast(FOURCC('L', 'A', 'N', '4')) << 32; if (endpoints.find(p2pID) != endpoints.end()) { @@ -4359,7 +4352,7 @@ void VoIPController::UpdateAudioBitrate() for (pair &_e : endpoints) { Endpoint &e = _e.second; - if (e.type == Endpoint::Type::UDP_P2P_INET || e.type == Endpoint::Type::UDP_P2P_LAN) + if (e.IsP2P()) { e.averageRTT = 0; e.rtts.Reset(); @@ -4511,14 +4504,15 @@ void VoIPController::SendPublicEndpointsRequest() publicEndpointsReqCount++; if (publicEndpointsReqCount < 10) { - messageThread.Post([this] { - if (waitingForRelayPeerInfo) - { - LOGW("Resending peer relay info request"); - SendPublicEndpointsRequest(); - } - }, - 5.0); + messageThread.Post( + [this] { + if (waitingForRelayPeerInfo) + { + LOGW("Resending peer relay info request"); + SendPublicEndpointsRequest(); + } + }, + 5.0); } else { @@ -4565,125 +4559,3 @@ void VoIPController::TickJitterBufferAndCongestionControl() } } } - -#pragma mark - Endpoint - -Endpoint::Endpoint(int64_t id, uint16_t port, const IPv4Address &_address, const IPv6Address &_v6address, Type type, unsigned char peerTag[16]) : address(NetworkAddress::IPv4(_address.addr)), v6address(NetworkAddress::IPv6(_v6address.addr)) -{ - this->id = id; - this->port = port; - this->type = type; - memcpy(this->peerTag, peerTag, 16); - if (type == Type::UDP_RELAY && ServerConfig::GetSharedInstance()->GetBoolean("force_tcp", false)) - this->type = Type::TCP_RELAY; - - lastPingSeq = 0; - lastPingTime = 0; - averageRTT = 0; - socket = NULL; - udpPongCount = 0; -} - -Endpoint::Endpoint(int64_t id, uint16_t port, const NetworkAddress _address, const NetworkAddress _v6address, Type type, unsigned char peerTag[16]) : address(_address), v6address(_v6address) -{ - this->id = id; - this->port = port; - this->type = type; - memcpy(this->peerTag, peerTag, 16); - if (type == Type::UDP_RELAY && ServerConfig::GetSharedInstance()->GetBoolean("force_tcp", false)) - this->type = Type::TCP_RELAY; - - lastPingSeq = 0; - lastPingTime = 0; - averageRTT = 0; - socket = NULL; - udpPongCount = 0; -} - -Endpoint::Endpoint() : address(NetworkAddress::Empty()), v6address(NetworkAddress::Empty()) -{ - lastPingSeq = 0; - lastPingTime = 0; - averageRTT = 0; - socket = NULL; - udpPongCount = 0; -} - -const NetworkAddress &Endpoint::GetAddress() const -{ - return IsIPv6Only() ? (NetworkAddress &)v6address : (NetworkAddress &)address; -} - -NetworkAddress &Endpoint::GetAddress() -{ - return IsIPv6Only() ? (NetworkAddress &)v6address : (NetworkAddress &)address; -} - -bool Endpoint::IsIPv6Only() const -{ - return address.IsEmpty() && !v6address.IsEmpty(); -} - -int64_t Endpoint::CleanID() const -{ - int64_t _id = id; - if (type == Type::TCP_RELAY) - { - _id = _id ^ ((int64_t)FOURCC('T', 'C', 'P', ' ') << 32); - } - if (IsIPv6Only()) - { - _id = _id ^ ((int64_t)FOURCC('I', 'P', 'v', '6') << 32); - } - return _id; -} - -Endpoint::~Endpoint() -{ - if (socket) - { - socket->Close(); - } -} - -#pragma mark - AudioInputTester - -AudioInputTester::AudioInputTester(std::string deviceID) : deviceID(std::move(deviceID)) -{ - io = audio::AudioIO::Create(deviceID, "default"); - if (io->Failed()) - { - LOGE("Audio IO failed"); - return; - } - input = io->GetInput(); - input->SetCallback([](unsigned char *data, size_t size, void *ctx) -> size_t { - reinterpret_cast(ctx)->Update(reinterpret_cast(data), size / 2); - return 0; - }, - this); - input->Start(); -} - -AudioInputTester::~AudioInputTester() -{ - input->Stop(); - delete io; -} - -void AudioInputTester::Update(int16_t *samples, size_t count) -{ - for (size_t i = 0; i < count; i++) - { - int16_t s = abs(samples[i]); - if (s > maxSample) - maxSample = s; - } -} - -float AudioInputTester::GetAndResetLevel() -{ - float s = maxSample; - maxSample = 0; - return s / (float)INT16_MAX; -} diff --git a/VoIPController.h b/VoIPController.h index f7dc41f..a6114cd 100755 --- a/VoIPController.h +++ b/VoIPController.h @@ -4,8 +4,7 @@ // you should have received with this source code distribution. // -#ifndef __VOIPCONTROLLER_H -#define __VOIPCONTROLLER_H +#pragma once #ifndef _WIN32 #include @@ -27,10 +26,12 @@ #include #include "video/ScreamCongestionController.h" #include "audio/AudioInput.h" +#include "audio/Device.h" #include "tools/BlockingQueue.h" #include "audio/AudioOutput.h" #include "audio/AudioIO.h" #include "controller/net/JitterBuffer.h" +#include "controller/net/Endpoint.h" #include "controller/audio/OpusDecoder.h" #include "controller/audio/OpusEncoder.h" #include "controller/audio/EchoCanceller.h" @@ -124,95 +125,6 @@ struct CellularCarrierInfo std::string countryCode; }; -// API compatibility -struct IPv4Address -{ - IPv4Address(std::string addr) : addr(addr){}; - std::string addr; -}; -struct IPv6Address -{ - IPv6Address(std::string addr) : addr(addr){}; - std::string addr; -}; - -class Endpoint -{ - friend class VoIPController; - friend class VoIPGroupController; - -public: - enum Type - { - UDP_P2P_INET = 1, - UDP_P2P_LAN, - UDP_RELAY, - TCP_RELAY - }; - - Endpoint(int64_t id, uint16_t port, const IPv4Address &address, const IPv6Address &v6address, Type type, unsigned char *peerTag); - Endpoint(int64_t id, uint16_t port, const NetworkAddress address, const NetworkAddress v6address, Type type, unsigned char *peerTag); - Endpoint(); - ~Endpoint(); - const NetworkAddress &GetAddress() const; - NetworkAddress &GetAddress(); - bool IsIPv6Only() const; - int64_t CleanID() const; - int64_t id; - uint16_t port; - NetworkAddress address; - NetworkAddress v6address; - Type type; - unsigned char peerTag[16]; - -private: - double lastPingTime; - uint32_t lastPingSeq; - HistoricBuffer rtts; - HistoricBuffer selfRtts; - std::map udpPingTimes; - double averageRTT; - std::shared_ptr socket; - int udpPongCount; - int totalUdpPings = 0; - int totalUdpPingReplies = 0; -}; - -class AudioDevice -{ -public: - std::string id; - std::string displayName; -}; - -class AudioOutputDevice : public AudioDevice -{ -}; - -class AudioInputDevice : public AudioDevice -{ -}; - -class AudioInputTester -{ -public: - AudioInputTester(const std::string deviceID); - ~AudioInputTester(); - TGVOIP_DISALLOW_COPY_AND_ASSIGN(AudioInputTester); - float GetAndResetLevel(); - bool Failed() - { - return io && io->Failed(); - } - -private: - void Update(int16_t *samples, size_t count); - audio::AudioIO *io = NULL; - audio::AudioInput *input = NULL; - int16_t maxSample = 0; - std::string deviceID; -}; - class PacketSender; namespace video { @@ -638,7 +550,7 @@ private: void KDF2(unsigned char *msgKey, size_t x, unsigned char *aesKey, unsigned char *aesIv); void SendPublicEndpointsRequest(); void SendPublicEndpointsRequest(const Endpoint &relay); - Endpoint &GetEndpointByType(int type); + Endpoint &GetEndpointByType(const Endpoint::Type type); void SendPacketReliably(unsigned char type, unsigned char *data, size_t len, double retryInterval, double timeout); uint32_t GenerateOutSeq(); void ActuallySendPacket(NetworkPacket pkt, Endpoint &ep); @@ -862,72 +774,5 @@ public: #endif }; -class VoIPGroupController : public VoIPController -{ -public: - VoIPGroupController(int32_t timeDifference); - virtual ~VoIPGroupController(); - void SetGroupCallInfo(unsigned char *encryptionKey, unsigned char *reflectorGroupTag, unsigned char *reflectorSelfTag, unsigned char *reflectorSelfSecret, unsigned char *reflectorSelfTagHash, int32_t selfUserID, NetworkAddress reflectorAddress, NetworkAddress reflectorAddressV6, uint16_t reflectorPort); - void AddGroupCallParticipant(int32_t userID, unsigned char *memberTagHash, unsigned char *serializedStreams, size_t streamsLength); - void RemoveGroupCallParticipant(int32_t userID); - float GetParticipantAudioLevel(int32_t userID); - virtual void SetMicMute(bool mute); - void SetParticipantVolume(int32_t userID, float volume); - void SetParticipantStreams(int32_t userID, unsigned char *serializedStreams, size_t length); - static size_t GetInitialStreams(unsigned char *buf, size_t size); - - struct Callbacks : public VoIPController::Callbacks - { - void (*updateStreams)(VoIPGroupController *, unsigned char *, size_t); - void (*participantAudioStateChanged)(VoIPGroupController *, int32_t, bool); - }; - void SetCallbacks(Callbacks callbacks); - virtual std::string GetDebugString(); - virtual void SetNetworkType(int type); - -protected: - virtual void ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcEndpoint); - virtual void SendInit(); - virtual void SendUdpPing(Endpoint &endpoint); - virtual void SendRelayPings(); - virtual void SendPacket(unsigned char *data, size_t len, Endpoint &ep, PendingOutgoingPacket &srcPacket); - virtual void WritePacketHeader(uint32_t seq, BufferOutputStream *s, unsigned char type, uint32_t length, PacketSender *sender = NULL); - virtual void OnAudioOutputReady(); - -private: - int32_t GetCurrentUnixtime(); - std::vector> DeserializeStreams(BufferInputStream &in); - void SendRecentPacketsRequest(); - void SendSpecialReflectorRequest(unsigned char *data, size_t len); - void SerializeAndUpdateOutgoingStreams(); - struct GroupCallParticipant - { - int32_t userID; - unsigned char memberTagHash[32]; - std::vector> streams; - AudioLevelMeter *levelMeter; - }; - std::vector participants; - unsigned char reflectorSelfTag[16]; - unsigned char reflectorSelfSecret[16]; - unsigned char reflectorSelfTagHash[32]; - int32_t userSelfID; - Endpoint groupReflector; - AudioMixer *audioMixer; - AudioLevelMeter selfLevelMeter; - Callbacks groupCallbacks; - struct PacketIdMapping - { - uint32_t seq; - uint16_t id; - double ackTime; - }; - std::vector recentSentPackets; - Mutex sentPacketsMutex; - Mutex participantsMutex; - int32_t timeDifference; -}; }; // namespace tgvoip - -#endif diff --git a/VoIPGroupController.cpp b/VoIPGroupController.cpp index 7bf40a5..29c230a 100644 --- a/VoIPGroupController.cpp +++ b/VoIPGroupController.cpp @@ -4,7 +4,7 @@ // you should have received with this source code distribution. // -#include "VoIPController.h" +#include "VoIPGroupController.h" #include "tools/logging.h" #include "VoIPServerConfig.h" #include "controller/PrivateDefines.h" diff --git a/VoIPGroupController.h b/VoIPGroupController.h new file mode 100644 index 0000000..36a66ba --- /dev/null +++ b/VoIPGroupController.h @@ -0,0 +1,75 @@ +#pragma once +#include "VoIPController.h" +#include "controller/net/Endpoint.h" +#include "controller/net/NetworkSocket.h" + +namespace tgvoip +{ + +class VoIPGroupController : public VoIPController +{ +public: + VoIPGroupController(int32_t timeDifference); + virtual ~VoIPGroupController(); + void SetGroupCallInfo(unsigned char *encryptionKey, unsigned char *reflectorGroupTag, unsigned char *reflectorSelfTag, unsigned char *reflectorSelfSecret, unsigned char *reflectorSelfTagHash, int32_t selfUserID, NetworkAddress reflectorAddress, NetworkAddress reflectorAddressV6, uint16_t reflectorPort); + void AddGroupCallParticipant(int32_t userID, unsigned char *memberTagHash, unsigned char *serializedStreams, size_t streamsLength); + void RemoveGroupCallParticipant(int32_t userID); + float GetParticipantAudioLevel(int32_t userID); + virtual void SetMicMute(bool mute); + void SetParticipantVolume(int32_t userID, float volume); + void SetParticipantStreams(int32_t userID, unsigned char *serializedStreams, size_t length); + static size_t GetInitialStreams(unsigned char *buf, size_t size); + + struct Callbacks : public VoIPController::Callbacks + { + void (*updateStreams)(VoIPGroupController *, unsigned char *, size_t); + void (*participantAudioStateChanged)(VoIPGroupController *, int32_t, bool); + }; + void SetCallbacks(Callbacks callbacks); + virtual std::string GetDebugString(); + virtual void SetNetworkType(int type); + +protected: + virtual void ProcessIncomingPacket(NetworkPacket &packet, Endpoint &srcEndpoint); + virtual void SendInit(); + virtual void SendUdpPing(Endpoint &endpoint); + virtual void SendRelayPings(); + virtual void SendPacket(unsigned char *data, size_t len, Endpoint &ep, PendingOutgoingPacket &srcPacket); + virtual void WritePacketHeader(uint32_t seq, BufferOutputStream *s, unsigned char type, uint32_t length, PacketSender *sender = NULL); + virtual void OnAudioOutputReady(); + +private: + int32_t GetCurrentUnixtime(); + std::vector> DeserializeStreams(BufferInputStream &in); + void SendRecentPacketsRequest(); + void SendSpecialReflectorRequest(unsigned char *data, size_t len); + void SerializeAndUpdateOutgoingStreams(); + struct GroupCallParticipant + { + int32_t userID; + unsigned char memberTagHash[32]; + std::vector> streams; + AudioLevelMeter *levelMeter; + }; + std::vector participants; + unsigned char reflectorSelfTag[16]; + unsigned char reflectorSelfSecret[16]; + unsigned char reflectorSelfTagHash[32]; + int32_t userSelfID; + Endpoint groupReflector; + AudioMixer *audioMixer; + AudioLevelMeter selfLevelMeter; + Callbacks groupCallbacks; + struct PacketIdMapping + { + uint32_t seq; + uint16_t id; + double ackTime; + }; + std::vector recentSentPackets; + Mutex sentPacketsMutex; + Mutex participantsMutex; + int32_t timeDifference; +}; + +} // namespace tgvoip \ No newline at end of file diff --git a/audio/AudioInputTester.cpp b/audio/AudioInputTester.cpp new file mode 100644 index 0000000..fbc114c --- /dev/null +++ b/audio/AudioInputTester.cpp @@ -0,0 +1,44 @@ +#include "AudioInputTester.h" +#include "../tools/logging.h" + +using namespace tgvoip; + +AudioInputTester::AudioInputTester(std::string deviceID) : deviceID(std::move(deviceID)) +{ + io = audio::AudioIO::Create(deviceID, "default"); + if (io->Failed()) + { + LOGE("Audio IO failed"); + return; + } + input = io->GetInput(); + input->SetCallback([](unsigned char *data, size_t size, void *ctx) -> size_t { + reinterpret_cast(ctx)->Update(reinterpret_cast(data), size / 2); + return 0; + }, + this); + input->Start(); +} + +AudioInputTester::~AudioInputTester() +{ + input->Stop(); + delete io; +} + +void AudioInputTester::Update(int16_t *samples, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + int16_t s = abs(samples[i]); + if (s > maxSample) + maxSample = s; + } +} + +float AudioInputTester::GetAndResetLevel() +{ + float s = maxSample; + maxSample = 0; + return s / (float)INT16_MAX; +} diff --git a/audio/AudioInputTester.h b/audio/AudioInputTester.h new file mode 100644 index 0000000..e00c914 --- /dev/null +++ b/audio/AudioInputTester.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "../controller/PrivateDefines.h" +#include "AudioIO.h" +#include "AudioInput.h" + +namespace tgvoip +{ + +class AudioInputTester +{ +public: + AudioInputTester(const std::string deviceID); + ~AudioInputTester(); + TGVOIP_DISALLOW_COPY_AND_ASSIGN(AudioInputTester); + float GetAndResetLevel(); + bool Failed() + { + return io && io->Failed(); + } + +private: + void Update(int16_t *samples, size_t count); + audio::AudioIO *io = NULL; + audio::AudioInput *input = NULL; + int16_t maxSample = 0; + std::string deviceID; +}; + +} // namespace tgvoip \ No newline at end of file diff --git a/audio/Device.h b/audio/Device.h new file mode 100644 index 0000000..5be456b --- /dev/null +++ b/audio/Device.h @@ -0,0 +1,22 @@ +#pragma once +#include + +namespace tgvoip +{ + +class AudioDevice +{ +public: + std::string id; + std::string displayName; +}; + +class AudioOutputDevice : public AudioDevice +{ +}; + +class AudioInputDevice : public AudioDevice +{ +}; + +} // namespace tgvoip \ No newline at end of file diff --git a/controller/PacketSender.h b/controller/PacketSender.h index 8e3abea..5e13036 100644 --- a/controller/PacketSender.h +++ b/controller/PacketSender.h @@ -43,7 +43,7 @@ protected: return controller->connectionInitTime; } - const HistoricBuffer &RTTHistory() + const HistoricBuffer &RTTHistory() const { return controller->rttHistory; } @@ -53,7 +53,7 @@ protected: return controller->messageThread; } - const VoIPController::ProtocolInfo &GetProtocolInfo() + const VoIPController::ProtocolInfo &GetProtocolInfo() const { return controller->protocolInfo; } @@ -63,7 +63,7 @@ protected: controller->SendStreamFlags(stm); } - const VoIPController::Config &GetConfig() + const VoIPController::Config &GetConfig() const { return controller->config; } diff --git a/controller/net/CongestionControl.cpp b/controller/net/CongestionControl.cpp index 4fbc8d0..7623536 100644 --- a/controller/net/CongestionControl.cpp +++ b/controller/net/CongestionControl.cpp @@ -4,28 +4,18 @@ // you should have received with this source code distribution. // -#include "controller/net/CongestionControl.h" +#include "CongestionControl.h" #include "VoIPController.h" #include "tools/logging.h" #include "VoIPServerConfig.h" -#include "controller/PrivateDefines.h" +#include "../PrivateDefines.h" #include #include using namespace tgvoip; -CongestionControl::CongestionControl() +CongestionControl::CongestionControl() : cwnd(static_cast(ServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024))) { - memset(inflightPackets, 0, sizeof(inflightPackets)); - tmpRtt = 0; - tmpRttCount = 0; - lastSentSeq = 0; - lastActionTime = 0; - lastActionRtt = 0; - stateTransitionTime = 0; - inflightDataSize = 0; - lossCount = 0; - cwnd = (size_t)ServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024); } CongestionControl::~CongestionControl() @@ -59,14 +49,14 @@ double CongestionControl::GetMinimumRTT() void CongestionControl::PacketAcknowledged(uint32_t seq) { - for (int i = 0; i < 100; i++) + for (auto &packet : inflightPackets) { - if (inflightPackets[i].seq == seq && inflightPackets[i].sendTime > 0) + if (packet.seq == seq && packet.sendTime > 0) { - tmpRtt += (VoIPController::GetCurrentTime() - inflightPackets[i].sendTime); + tmpRtt += (VoIPController::GetCurrentTime() - packet.sendTime); tmpRttCount++; - inflightPackets[i].sendTime = 0; - inflightDataSize -= inflightPackets[i].size; + packet.sendTime = 0; + inflightDataSize -= packet.size; break; } } @@ -82,8 +72,7 @@ void CongestionControl::PacketSent(uint32_t seq, size_t size) lastSentSeq = seq; double smallestSendTime = INFINITY; tgvoip_congestionctl_packet_t *slot = NULL; - int i; - for (i = 0; i < 100; i++) + for (size_t i = 0; i < inflightPackets.size(); i++) { if (inflightPackets[i].sendTime == 0) { @@ -111,12 +100,12 @@ void CongestionControl::PacketSent(uint32_t seq, size_t size) void CongestionControl::PacketLost(uint32_t seq) { - for (int i = 0; i < 100; i++) + for (auto &packet : inflightPackets) { - if (inflightPackets[i].seq == seq && inflightPackets[i].sendTime > 0) + if (packet.seq == seq && packet.sendTime > 0) { - inflightPackets[i].sendTime = 0; - inflightDataSize -= inflightPackets[i].size; + packet.sendTime = 0; + inflightDataSize -= packet.size; lossCount++; break; } @@ -132,15 +121,14 @@ void CongestionControl::Tick() tmpRtt = 0; tmpRttCount = 0; } - int i; - for (i = 0; i < 100; i++) + for (auto &packet : inflightPackets) { - if (inflightPackets[i].sendTime != 0 && VoIPController::GetCurrentTime() - inflightPackets[i].sendTime > 2) + if (packet.sendTime != 0 && VoIPController::GetCurrentTime() - packet.sendTime > TGVOIP_CONCTL_LOST_AFTER) { - inflightPackets[i].sendTime = 0; - inflightDataSize -= inflightPackets[i].size; + packet.sendTime = 0; + inflightDataSize -= packet.size; lossCount++; - LOGD("Packet with seq %u was not acknowledged", inflightPackets[i].seq); + LOGD("Packet with seq %u was not acknowledged", packet.seq); } } inflightHistory.Add(inflightDataSize); @@ -150,6 +138,7 @@ int CongestionControl::GetBandwidthControlAction() { if (VoIPController::GetCurrentTime() - lastActionTime < 1) return TGVOIP_CONCTL_ACT_NONE; + size_t inflightAvg = GetInflightDataSize(); size_t max = cwnd + cwnd / 10; size_t min = cwnd - cwnd / 10; diff --git a/controller/net/CongestionControl.h b/controller/net/CongestionControl.h index 9df7fbf..2d197e2 100644 --- a/controller/net/CongestionControl.h +++ b/controller/net/CongestionControl.h @@ -16,6 +16,8 @@ #define TGVOIP_CONCTL_ACT_DECREASE 2 #define TGVOIP_CONCTL_ACT_NONE 0 +#define TGVOIP_CONCTL_LOST_AFTER 2 + namespace tgvoip { @@ -49,16 +51,16 @@ public: private: HistoricBuffer rttHistory; HistoricBuffer inflightHistory; - tgvoip_congestionctl_packet_t inflightPackets[100]; - uint32_t lossCount; - double tmpRtt; - double lastActionTime; - double lastActionRtt; - double stateTransitionTime; - int tmpRttCount; - uint32_t lastSentSeq; - uint32_t tickCount; - size_t inflightDataSize; + std::array inflightPackets{}; + uint32_t lossCount = 0; + double tmpRtt = 0.0; + double lastActionTime = 0; + double lastActionRtt = 0; + double stateTransitionTime = 0; + uint32_t tmpRttCount = 0; + uint32_t lastSentSeq = 0; + uint32_t tickCount = 0; + size_t inflightDataSize = 0; size_t cwnd; }; } // namespace tgvoip diff --git a/controller/net/Endpoint.cpp b/controller/net/Endpoint.cpp new file mode 100644 index 0000000..39ca7c7 --- /dev/null +++ b/controller/net/Endpoint.cpp @@ -0,0 +1,87 @@ +// +// libtgvoip is free and unencumbered public domain software. +// For more information, see http://unlicense.org or the UNLICENSE file +// you should have received with this source code distribution. +// +#include "Endpoint.h" +#include "../../VoIPServerConfig.h" +#include "../PrivateDefines.h" +using namespace tgvoip; + +Endpoint::Endpoint(int64_t id, uint16_t port, const IPv4Address &_address, const IPv6Address &_v6address, Type type, unsigned char peerTag[16]) : address(NetworkAddress::IPv4(_address.addr)), v6address(NetworkAddress::IPv6(_v6address.addr)) +{ + this->id = id; + this->port = port; + this->type = type; + memcpy(this->peerTag, peerTag, 16); + if (type == Type::UDP_RELAY && ServerConfig::GetSharedInstance()->GetBoolean("force_tcp", false)) + this->type = Type::TCP_RELAY; + + lastPingSeq = 0; + lastPingTime = 0; + averageRTT = 0; + socket = NULL; + udpPongCount = 0; +} + +Endpoint::Endpoint(int64_t id, uint16_t port, const NetworkAddress _address, const NetworkAddress _v6address, Type type, unsigned char peerTag[16]) : address(_address), v6address(_v6address) +{ + this->id = id; + this->port = port; + this->type = type; + memcpy(this->peerTag, peerTag, 16); + if (type == Type::UDP_RELAY && ServerConfig::GetSharedInstance()->GetBoolean("force_tcp", false)) + this->type = Type::TCP_RELAY; + + lastPingSeq = 0; + lastPingTime = 0; + averageRTT = 0; + socket = NULL; + udpPongCount = 0; +} + +Endpoint::Endpoint() : address(NetworkAddress::Empty()), v6address(NetworkAddress::Empty()) +{ + lastPingSeq = 0; + lastPingTime = 0; + averageRTT = 0; + socket = NULL; + udpPongCount = 0; +} + +const NetworkAddress &Endpoint::GetAddress() const +{ + return IsIPv6Only() ? (NetworkAddress &)v6address : (NetworkAddress &)address; +} + +NetworkAddress &Endpoint::GetAddress() +{ + return IsIPv6Only() ? (NetworkAddress &)v6address : (NetworkAddress &)address; +} + +bool Endpoint::IsIPv6Only() const +{ + return address.IsEmpty() && !v6address.IsEmpty(); +} + +int64_t Endpoint::CleanID() const +{ + int64_t _id = id; + if (type == Type::TCP_RELAY) + { + _id = _id ^ ((int64_t)FOURCC('T', 'C', 'P', ' ') << 32); + } + if (IsIPv6Only()) + { + _id = _id ^ ((int64_t)FOURCC('I', 'P', 'v', '6') << 32); + } + return _id; +} + +Endpoint::~Endpoint() +{ + if (socket) + { + socket->Close(); + } +} diff --git a/controller/net/Endpoint.h b/controller/net/Endpoint.h new file mode 100644 index 0000000..f1b571c --- /dev/null +++ b/controller/net/Endpoint.h @@ -0,0 +1,67 @@ +// +// libtgvoip is free and unencumbered public domain software. +// For more information, see http://unlicense.org or the UNLICENSE file +// you should have received with this source code distribution. +// + +#pragma once +#include "NetworkSocket.h" +#include +#include + +namespace tgvoip +{ +class VoIPGroupController; +class VoIPController; + +class Endpoint +{ + friend class VoIPController; + friend class VoIPGroupController; + +public: + enum Type + { + UDP_P2P_INET = 1, + UDP_P2P_LAN, + UDP_RELAY, + TCP_RELAY + }; + + Endpoint(int64_t id, uint16_t port, const IPv4Address &address, const IPv6Address &v6address, Type type, unsigned char *peerTag); + Endpoint(int64_t id, uint16_t port, const NetworkAddress address, const NetworkAddress v6address, Type type, unsigned char *peerTag); + Endpoint(); + ~Endpoint(); + const NetworkAddress &GetAddress() const; + NetworkAddress &GetAddress(); + bool IsIPv6Only() const; + int64_t CleanID() const; + int64_t id; + uint16_t port; + NetworkAddress address; + NetworkAddress v6address; + Type type; + unsigned char peerTag[16]; + + const bool IsP2P() const + { + return type == UDP_P2P_INET || type == UDP_P2P_LAN; + } + const bool IsReflector() const + { + return type == UDP_RELAY || type == TCP_RELAY; + } + +private: + double lastPingTime; + uint32_t lastPingSeq; + HistoricBuffer rtts; + HistoricBuffer selfRtts; + std::map udpPingTimes; + double averageRTT; + std::shared_ptr socket; + int udpPongCount; + int totalUdpPings = 0; + int totalUdpPingReplies = 0; +}; +} // namespace tgvoip \ No newline at end of file diff --git a/controller/net/NetworkSocket.h b/controller/net/NetworkSocket.h index 1ba4f6d..93e123b 100644 --- a/controller/net/NetworkSocket.h +++ b/controller/net/NetworkSocket.h @@ -16,6 +16,20 @@ namespace tgvoip { + +// API compatibility +struct IPv4Address +{ + IPv4Address(std::string addr) : addr(addr){}; + std::string addr; +}; +struct IPv6Address +{ + IPv6Address(std::string addr) : addr(addr){}; + std::string addr; +}; + + enum class NetworkProtocol { UDP = 0, diff --git a/os/posix/NetworkSocketPosix.cpp b/os/posix/NetworkSocketPosix.cpp index d41053b..a8839ac 100644 --- a/os/posix/NetworkSocketPosix.cpp +++ b/os/posix/NetworkSocketPosix.cpp @@ -676,6 +676,7 @@ bool NetworkSocketPosix::Select(std::vector &readFds, std::vect } else if (anyFailed) { + LOGE("Select failed, zeroing out"); FD_ZERO(&readSet); FD_ZERO(&writeSet); } diff --git a/tools/Buffers.h b/tools/Buffers.h index 3b0a8ab..9a9e98a 100644 --- a/tools/Buffers.h +++ b/tools/Buffers.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "tools/threading.h" @@ -256,7 +257,6 @@ class HistoricBuffer public: HistoricBuffer() { - std::fill(data.begin(), data.end(), static_cast(0)); } AVG_T Average() const @@ -267,7 +267,7 @@ public: AVG_T Average(size_t firstN) const { AVG_T avg = static_cast(0); - for (size_t i = 0; i < firstN; i++) + for (size_t i = 0; i < firstN; i++) // Manual iteration required to wrap around array with specific offset { avg += (*this)[i]; } @@ -299,24 +299,12 @@ public: T Min() const { - T min = std::numeric_limits::max(); - for (T i : data) - { - if (i < min) - min = i; - } - return min; + return *std::min_element(data.begin(), data.end()); } T Max() const { - T max = std::numeric_limits::min(); - for (T i : data) - { - if (i > max) - max = i; - } - return max; + return *std::max_element(data.begin(), data.end()); } void Reset() @@ -330,8 +318,8 @@ public: 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) - _i = size + _i; // wtf + if (_i < 0) // Wrap around offset a-la posmod + _i = size + _i; return data[_i]; } @@ -340,8 +328,8 @@ public: 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) - _i = size + _i; // wtf + if (_i < 0) // Wrap around offset a-la posmod + _i = size + _i; return data[_i]; } @@ -351,7 +339,7 @@ public: } private: - std::array data; + std::array data{}; ptrdiff_t offset = 0; };