2017-04-17 20:57:07 +02:00
//
// 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.
//
# ifndef _WIN32
# include <unistd.h>
# include <sys/time.h>
# endif
2017-02-02 17:24:40 +01:00
# include <errno.h>
# include <string.h>
# include <wchar.h>
# include "VoIPController.h"
2020-01-22 12:43:51 +01:00
# include "tools/logging.h"
# include "tools/threading.h"
# include "tools/Buffers.h"
2020-01-22 12:51:17 +01:00
# include "controller/audio/OpusEncoder.h"
# include "controller/audio/OpusDecoder.h"
2017-03-30 16:06:59 +02:00
# include "VoIPServerConfig.h"
2020-01-22 12:43:51 +01:00
# include "controller/PrivateDefines.h"
2020-01-22 12:54:35 +01:00
# include "tools/json11.hpp"
2020-01-22 12:43:51 +01:00
# include "controller/PacketSender.h"
2020-01-22 12:54:35 +01:00
# include "video/VideoPacketSender.h"
2017-02-02 17:24:40 +01:00
# include <assert.h>
# include <time.h>
# include <math.h>
# include <exception>
# include <stdexcept>
2017-07-03 03:42:49 +02:00
# include <algorithm>
2019-02-11 17:01:45 +01:00
# include <sstream>
2018-08-24 01:29:07 +02:00
# include <inttypes.h>
2018-08-24 17:38:09 +02:00
# include <float.h>
2019-12-24 19:40:50 +01:00
# ifdef HAVE_CONFIG_H
# include <opus/opus.h>
# else
2019-12-24 19:57:14 +01:00
# include <opus/opus.h>
2019-12-24 19:40:50 +01:00
# endif
2017-07-03 03:42:49 +02:00
2020-01-22 12:43:51 +01:00
inline int pad4 ( int x )
{
int r = PAD4 ( x ) ;
if ( r = = 4 )
2017-07-03 03:42:49 +02:00
return 0 ;
return r ;
}
2017-04-17 20:57:07 +02:00
using namespace tgvoip ;
2018-06-04 21:37:43 +02:00
using namespace std ;
2017-02-02 17:24:40 +01:00
# ifdef __APPLE__
2017-03-30 16:06:59 +02:00
# include "os/darwin/AudioUnitIO.h"
2017-02-02 17:24:40 +01:00
# include <mach/mach_time.h>
2020-01-22 12:43:51 +01:00
double VoIPController : : machTimebase = 0 ;
uint64_t VoIPController : : machTimestart = 0 ;
2017-04-17 20:57:07 +02:00
# endif
# ifdef _WIN32
int64_t VoIPController : : win32TimeScale = 0 ;
bool VoIPController : : didInitWin32TimeScale = false ;
2017-02-02 17:24:40 +01:00
# endif
2018-11-09 16:44:01 +01:00
# ifdef __ANDROID__
# include "os/android/JNIUtilities.h"
2018-11-21 19:22:31 +01:00
# include "os/android/AudioInputAndroid.h"
2020-01-22 12:43:51 +01:00
# include "controller/net/NetworkSocket.h"
2019-04-15 01:43:10 +02:00
2018-11-09 16:44:01 +01:00
extern jclass jniUtilitiesClass ;
# endif
2018-09-01 00:59:09 +02:00
# if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
# include "audio/AudioIOCallback.h"
# endif
2019-04-15 01:43:10 +02:00
# define ENFORCE_MSG_THREAD assert(messageThread.IsCurrent())
2020-01-22 12:43:51 +01:00
extern FILE * tgvoipLogFile ;
2017-03-30 16:06:59 +02:00
2018-11-18 00:36:55 +01:00
# pragma mark - Public API
2017-07-03 03:42:49 +02:00
VoIPController : : VoIPController ( ) : activeNetItfName ( " " ) ,
currentAudioInput ( " default " ) ,
currentAudioOutput ( " default " ) ,
proxyAddress ( " " ) ,
proxyUsername ( " " ) ,
2019-04-15 01:43:10 +02:00
proxyPassword ( " " ) ,
2020-01-22 12:43:51 +01:00
ecAudioPackets ( 4 ) ,
rawSendQueue ( 64 )
{
seq = 1 ;
lastRemoteSeq = 0 ;
state = STATE_WAIT_INIT ;
audioInput = NULL ;
audioOutput = NULL ;
encoder = NULL ;
audioOutStarted = false ;
audioTimestampIn = 0 ;
audioTimestampOut = 0 ;
stopping = false ;
2018-06-04 21:37:43 +02:00
memset ( & stats , 0 , sizeof ( TrafficStats ) ) ;
2020-01-22 12:43:51 +01:00
lastRemoteAckSeq = 0 ;
lastSentSeq = 0 ;
recvLossCount = 0 ;
packetsReceived = 0 ;
waitingForAcks = false ;
networkType = NET_TYPE_UNKNOWN ;
echoCanceller = NULL ;
dontSendPackets = 0 ;
micMuted = false ;
waitingForRelayPeerInfo = false ;
allowP2p = true ;
dataSavingMode = false ;
publicEndpointsReqTime = 0 ;
connectionInitTime = 0 ;
lastRecvPacketTime = 0 ;
dataSavingRequestedByPeer = false ;
peerVersion = 0 ;
conctl = new CongestionControl ( ) ;
prevSendLossCount = 0 ;
receivedInit = false ;
receivedInitAck = false ;
statsDump = NULL ;
useTCP = false ;
useUDP = true ;
didAddTcpRelays = false ;
udpPingCount = 0 ;
lastUdpPingTime = 0 ;
proxyProtocol = PROXY_NONE ;
proxyPort = 0 ;
selectCanceller = SocketSelectCanceller : : Create ( ) ;
udpSocket = NetworkSocket : : Create ( NetworkProtocol : : UDP ) ;
realUdpSocket = udpSocket ;
udpConnectivityState = UDP_UNKNOWN ;
echoCancellationStrength = 1 ;
peerCapabilities = 0 ;
callbacks = { 0 } ;
didReceiveGroupCallKey = false ;
didReceiveGroupCallKeyAck = false ;
didSendGroupCallKey = false ;
didSendUpgradeRequest = false ;
didInvokeUpgradeCallback = false ;
connectionMaxLayer = 0 ;
useMTProto2 = false ;
setCurrentEndpointToTCP = false ;
useIPv6 = false ;
peerIPv6Available = false ;
shittyInternetMode = false ;
didAddIPv6Relays = false ;
didSendIPv6Endpoint = false ;
2018-08-24 01:29:07 +02:00
unsentStreamPackets . store ( 0 ) ;
2020-01-22 12:43:51 +01:00
runReceiver = false ;
sendThread = NULL ;
recvThread = NULL ;
maxAudioBitrate = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_max_bitrate " , 20000 ) ;
maxAudioBitrateGPRS = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_max_bitrate_gprs " , 8000 ) ;
maxAudioBitrateEDGE = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_max_bitrate_edge " , 16000 ) ;
maxAudioBitrateSaving = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_max_bitrate_saving " , 8000 ) ;
initAudioBitrate = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_init_bitrate " , 16000 ) ;
initAudioBitrateGPRS = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_init_bitrate_gprs " , 8000 ) ;
initAudioBitrateEDGE = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_init_bitrate_edge " , 8000 ) ;
initAudioBitrateSaving = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_init_bitrate_saving " , 8000 ) ;
audioBitrateStepIncr = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_bitrate_step_incr " , 1000 ) ;
audioBitrateStepDecr = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_bitrate_step_decr " , 1000 ) ;
minAudioBitrate = ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " audio_min_bitrate " , 8000 ) ;
relaySwitchThreshold = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " relay_switch_threshold " , 0.8 ) ;
p2pToRelaySwitchThreshold = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " p2p_to_relay_switch_threshold " , 0.6 ) ;
relayToP2pSwitchThreshold = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " relay_to_p2p_switch_threshold " , 0.8 ) ;
reconnectingTimeout = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " reconnecting_state_timeout " , 2.0 ) ;
needRateFlags = static_cast < uint32_t > ( ServerConfig : : GetSharedInstance ( ) - > GetInt ( " rate_flags " , 0xFFFFFFFF ) ) ;
rateMaxAcceptableRTT = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " rate_min_rtt " , 0.6 ) ;
rateMaxAcceptableSendLoss = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " rate_min_send_loss " , 0.2 ) ;
packetLossToEnableExtraEC = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " packet_loss_for_extra_ec " , 0.02 ) ;
maxUnsentStreamPackets = static_cast < uint32_t > ( ServerConfig : : GetSharedInstance ( ) - > GetInt ( " max_unsent_stream_packets " , 2 ) ) ;
unackNopThreshold = static_cast < uint32_t > ( ServerConfig : : GetSharedInstance ( ) - > GetInt ( " unack_nop_threshold " , 10 ) ) ;
2017-03-30 16:06:59 +02:00
2017-02-02 17:24:40 +01:00
# ifdef __APPLE__
2020-01-22 12:43:51 +01:00
machTimestart = 0 ;
2017-02-02 17:24:40 +01:00
# endif
2017-05-09 22:26:18 +02:00
2020-01-22 12:43:51 +01:00
shared_ptr < Stream > stm = make_shared < Stream > ( ) ;
stm - > id = 1 ;
stm - > type = STREAM_TYPE_AUDIO ;
stm - > codec = CODEC_OPUS ;
stm - > enabled = 1 ;
stm - > frameDuration = 60 ;
2017-02-02 17:24:40 +01:00
outgoingStreams . push_back ( stm ) ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
VoIPController : : ~ VoIPController ( )
{
2017-04-17 20:57:07 +02:00
LOGD ( " Entered VoIPController::~VoIPController " ) ;
2020-01-22 12:43:51 +01:00
if ( ! stopping )
{
2018-05-15 20:23:46 +02:00
LOGE ( " !!!!!!!!!!!!!!!!!!!! CALL controller->Stop() BEFORE DELETING THE CONTROLLER OBJECT !!!!!!!!!!!!!!!!!!!!!!!1 " ) ;
abort ( ) ;
}
2017-02-02 17:24:40 +01:00
LOGD ( " before close socket " ) ;
2020-01-22 12:43:51 +01:00
if ( udpSocket )
2017-07-03 03:42:49 +02:00
delete udpSocket ;
2020-01-22 12:43:51 +01:00
if ( udpSocket ! = realUdpSocket )
2017-07-03 03:42:49 +02:00
delete realUdpSocket ;
2018-11-09 16:44:01 +01:00
LOGD ( " before delete audioIO " ) ;
2020-01-22 12:43:51 +01:00
if ( audioIO )
{
2018-11-09 16:44:01 +01:00
delete audioIO ;
2020-01-22 12:43:51 +01:00
audioInput = NULL ;
audioOutput = NULL ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
for ( auto _stm = incomingStreams . begin ( ) ; _stm ! = incomingStreams . end ( ) ; + + _stm )
{
shared_ptr < Stream > stm = * _stm ;
2018-05-15 20:23:46 +02:00
LOGD ( " before stop decoder " ) ;
2020-01-22 12:43:51 +01:00
if ( stm - > decoder )
{
2018-05-15 20:23:46 +02:00
stm - > decoder - > Stop ( ) ;
}
2017-02-02 17:24:40 +01:00
}
LOGD ( " before delete encoder " ) ;
2020-01-22 12:43:51 +01:00
if ( encoder )
{
2017-02-02 17:24:40 +01:00
encoder - > Stop ( ) ;
delete encoder ;
}
LOGD ( " before delete echo canceller " ) ;
2020-01-22 12:43:51 +01:00
if ( echoCanceller )
{
2017-02-02 17:24:40 +01:00
echoCanceller - > Stop ( ) ;
delete echoCanceller ;
}
delete conctl ;
2020-01-22 12:43:51 +01:00
if ( statsDump )
2017-04-28 13:17:56 +02:00
fclose ( statsDump ) ;
2017-07-03 03:42:49 +02:00
delete selectCanceller ;
LOGD ( " Left VoIPController::~VoIPController " ) ;
2020-01-22 12:43:51 +01:00
if ( tgvoipLogFile )
{
FILE * log = tgvoipLogFile ;
tgvoipLogFile = NULL ;
2019-02-10 13:28:22 +01:00
fclose ( log ) ;
}
2019-12-24 19:40:50 +01:00
# if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
2020-01-22 12:43:51 +01:00
if ( preprocDecoder )
{
opus_decoder_destroy ( preprocDecoder ) ;
preprocDecoder = nullptr ;
2019-12-24 19:40:50 +01:00
}
# endif
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : Stop ( )
{
2018-05-15 20:23:46 +02:00
LOGD ( " Entered VoIPController::Stop " ) ;
2020-01-22 12:43:51 +01:00
stopping = true ;
runReceiver = false ;
2018-05-15 20:23:46 +02:00
LOGD ( " before shutdown socket " ) ;
2020-01-22 12:43:51 +01:00
if ( udpSocket )
2018-05-15 20:23:46 +02:00
udpSocket - > Close ( ) ;
2020-01-22 12:43:51 +01:00
if ( realUdpSocket ! = udpSocket )
2018-05-15 20:23:46 +02:00
realUdpSocket - > Close ( ) ;
selectCanceller - > CancelSelect ( ) ;
2019-04-15 01:43:10 +02:00
//Buffer emptyBuf(0);
2018-11-09 16:44:01 +01:00
//PendingOutgoingPacket emptyPacket{0, 0, 0, move(emptyBuf), 0};
//sendQueue->Put(move(emptyPacket));
2019-04-15 01:43:10 +02:00
rawSendQueue . Put ( RawPendingOutgoingPacket { NetworkPacket : : Empty ( ) , nullptr } ) ;
2018-05-15 20:23:46 +02:00
LOGD ( " before join sendThread " ) ;
2020-01-22 12:43:51 +01:00
if ( sendThread )
{
2018-05-15 20:23:46 +02:00
sendThread - > Join ( ) ;
delete sendThread ;
}
LOGD ( " before join recvThread " ) ;
2020-01-22 12:43:51 +01:00
if ( recvThread )
{
2018-05-15 20:23:46 +02:00
recvThread - > Join ( ) ;
delete recvThread ;
}
2018-07-17 18:48:21 +02:00
LOGD ( " before stop messageThread " ) ;
messageThread . Stop ( ) ;
2018-05-25 21:14:45 +02:00
{
LOGD ( " Before stop audio I/O " ) ;
MutexGuard m ( audioIOMutex ) ;
2020-01-22 12:43:51 +01:00
if ( audioInput )
{
2018-05-25 21:14:45 +02:00
audioInput - > Stop ( ) ;
2018-08-28 22:41:01 +02:00
audioInput - > SetCallback ( NULL , NULL ) ;
}
2020-01-22 12:43:51 +01:00
if ( audioOutput )
{
2018-05-25 21:14:45 +02:00
audioOutput - > Stop ( ) ;
2018-08-28 22:41:01 +02:00
audioOutput - > SetCallback ( NULL , NULL ) ;
}
2018-05-25 21:14:45 +02:00
}
2020-01-22 12:43:51 +01:00
if ( videoPacketSender )
{
2019-04-15 01:43:10 +02:00
LOGD ( " before delete video packet sender " ) ;
delete videoPacketSender ;
2020-01-22 12:43:51 +01:00
videoPacketSender = NULL ;
2019-04-15 01:43:10 +02:00
}
2018-11-09 16:44:01 +01:00
LOGD ( " Left VoIPController::Stop [need rate = %d] " , ( int ) needRate ) ;
}
2020-01-22 12:43:51 +01:00
bool VoIPController : : NeedRate ( )
{
2019-01-08 04:28:25 +01:00
return needRate & & ServerConfig : : GetSharedInstance ( ) - > GetBoolean ( " bad_call_rating " , false ) ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetRemoteEndpoints ( vector < Endpoint > endpoints , bool allowP2p , int32_t connectionMaxLayer )
{
2018-05-15 20:23:46 +02:00
LOGW ( " Set remote endpoints, allowP2P=%d, connectionMaxLayer=%u " , allowP2p ? 1 : 0 , connectionMaxLayer ) ;
2019-04-15 01:43:10 +02:00
assert ( ! runReceiver ) ;
2020-01-22 12:43:51 +01:00
preferredRelay = 0 ;
2019-04-15 01:43:10 +02:00
this - > endpoints . clear ( ) ;
2020-01-22 12:43:51 +01:00
didAddTcpRelays = false ;
useTCP = true ;
for ( auto it = endpoints . begin ( ) ; it ! = endpoints . end ( ) ; + + it )
{
if ( this - > endpoints . find ( it - > id ) ! = this - > endpoints . end ( ) )
2019-04-15 01:43:10 +02:00
LOGE ( " Endpoint IDs are not unique! " ) ;
2020-01-22 12:43:51 +01:00
this - > endpoints [ it - > id ] = * it ;
if ( currentEndpoint = = 0 )
currentEndpoint = it - > id ;
if ( it - > type = = Endpoint : : Type : : TCP_RELAY )
didAddTcpRelays = true ;
if ( it - > type = = Endpoint : : Type : : UDP_RELAY )
useTCP = false ;
LOGV ( " Adding endpoint: %s:%d, %s " , it - > address . ToString ( ) . c_str ( ) , it - > port , it - > type = = Endpoint : : Type : : UDP_RELAY ? " UDP " : " TCP " ) ;
}
preferredRelay = currentEndpoint ;
this - > allowP2p = allowP2p ;
this - > connectionMaxLayer = connectionMaxLayer ;
if ( connectionMaxLayer > = 74 )
{
useMTProto2 = true ;
2018-05-15 20:23:46 +02:00
}
2018-06-04 21:37:43 +02:00
AddIPv6Relays ( ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : Start ( )
{
2017-02-02 17:24:40 +01:00
LOGW ( " Starting voip controller " ) ;
2017-07-03 03:42:49 +02:00
udpSocket - > Open ( ) ;
2020-01-22 12:43:51 +01:00
if ( udpSocket - > IsFailed ( ) )
{
2017-07-03 03:42:49 +02:00
SetState ( STATE_FAILED ) ;
return ;
}
2017-03-31 07:33:30 +02:00
2020-01-22 12:43:51 +01:00
runReceiver = true ;
recvThread = new Thread ( bind ( & VoIPController : : RunRecvThread , this ) ) ;
2018-05-15 20:23:46 +02:00
recvThread - > SetName ( " VoipRecv " ) ;
recvThread - > Start ( ) ;
2018-07-17 18:48:21 +02:00
messageThread . Start ( ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : Connect ( )
{
assert ( state ! = STATE_WAIT_INIT_ACK ) ;
connectionInitTime = GetCurrentTime ( ) ;
if ( config . initTimeout = = 0.0 )
{
2018-07-17 18:48:21 +02:00
LOGE ( " Init timeout is 0 -- did you forget to set config? " ) ;
2020-01-22 12:43:51 +01:00
config . initTimeout = 30.0 ;
2018-07-17 18:48:21 +02:00
}
2018-11-09 16:44:01 +01:00
//InitializeTimers();
//SendInit();
2020-01-22 12:43:51 +01:00
sendThread = new Thread ( bind ( & VoIPController : : RunSendThread , this ) ) ;
2018-11-09 16:44:01 +01:00
sendThread - > SetName ( " VoipSend " ) ;
sendThread - > Start ( ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetEncryptionKey ( char * key , bool isOutgoing )
{
2017-02-02 17:24:40 +01:00
memcpy ( encryptionKey , key , 256 ) ;
uint8_t sha1 [ SHA1_LENGTH ] ;
2020-01-22 12:43:51 +01:00
crypto . sha1 ( ( uint8_t * ) encryptionKey , 256 , sha1 ) ;
memcpy ( keyFingerprint , sha1 + ( SHA1_LENGTH - 8 ) , 8 ) ;
2017-02-02 17:24:40 +01:00
uint8_t sha256 [ SHA256_LENGTH ] ;
2020-01-22 12:43:51 +01:00
crypto . sha256 ( ( uint8_t * ) encryptionKey , 256 , sha256 ) ;
memcpy ( callID , sha256 + ( SHA256_LENGTH - 16 ) , 16 ) ;
this - > isOutgoing = isOutgoing ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetNetworkType ( int type )
{
networkType = type ;
2018-11-18 00:36:55 +01:00
UpdateDataSavingState ( ) ;
UpdateAudioBitrateLimit ( ) ;
2020-01-22 12:43:51 +01:00
myIPv6 = NetworkAddress : : Empty ( ) ;
string itfName = udpSocket - > GetLocalInterfaceInfo ( NULL , & myIPv6 ) ;
2019-01-08 04:28:25 +01:00
LOGI ( " set network type: %s, active interface %s " , NetworkTypeToString ( type ) . c_str ( ) , itfName . c_str ( ) ) ;
2018-11-18 00:36:55 +01:00
LOGI ( " Local IPv6 address: %s " , myIPv6 . ToString ( ) . c_str ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( IS_MOBILE_NETWORK ( networkType ) )
{
CellularCarrierInfo carrier = GetCarrierInfo ( ) ;
if ( ! carrier . name . empty ( ) )
{
2019-01-08 04:28:25 +01:00
LOGI ( " Carrier: %s [%s; mcc=%s, mnc=%s] " , carrier . name . c_str ( ) , carrier . countryCode . c_str ( ) , carrier . mcc . c_str ( ) , carrier . mnc . c_str ( ) ) ;
}
}
2020-01-22 12:43:51 +01:00
if ( itfName ! = activeNetItfName )
{
2018-11-18 00:36:55 +01:00
udpSocket - > OnActiveInterfaceChanged ( ) ;
LOGI ( " Active network interface changed: %s -> %s " , activeNetItfName . c_str ( ) , itfName . c_str ( ) ) ;
2020-01-22 12:43:51 +01:00
bool isFirstChange = activeNetItfName . length ( ) = = 0 & & state ! = STATE_ESTABLISHED & & state ! = STATE_RECONNECTING ;
activeNetItfName = itfName ;
if ( isFirstChange )
2018-11-18 00:36:55 +01:00
return ;
2020-01-22 12:43:51 +01:00
messageThread . Post ( [ this ] {
wasNetworkHandover = true ;
if ( currentEndpoint )
{
const Endpoint & _currentEndpoint = endpoints . at ( currentEndpoint ) ;
const Endpoint & _preferredRelay = endpoints . at ( preferredRelay ) ;
if ( _currentEndpoint . type ! = Endpoint : : Type : : UDP_RELAY )
{
if ( _preferredRelay . type = = Endpoint : : Type : : UDP_RELAY )
currentEndpoint = preferredRelay ;
2019-04-15 01:43:10 +02:00
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
constexpr int64_t lanID = ( int64_t ) ( FOURCC ( ' L ' , ' A ' , ' N ' , ' 4 ' ) ) < < 32 ;
2019-04-15 01:43:10 +02:00
endpoints . erase ( lanID ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
Endpoint & endpoint = e . second ;
if ( endpoint . type = = Endpoint : : Type : : UDP_RELAY & & useTCP )
{
useTCP = false ;
if ( _preferredRelay . type = = Endpoint : : Type : : TCP_RELAY )
{
preferredRelay = currentEndpoint = endpoint . id ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
}
else if ( endpoint . type = = Endpoint : : Type : : TCP_RELAY & & endpoint . socket )
{
2019-04-15 01:43:10 +02:00
endpoint . socket - > Close ( ) ;
//delete endpoint.socket;
//endpoint.socket=NULL;
2018-11-18 00:36:55 +01:00
}
2019-04-15 01:43:10 +02:00
//if(endpoint->type==Endpoint::Type::UDP_P2P_INET){
2020-01-22 12:43:51 +01:00
endpoint . averageRTT = 0 ;
2019-04-15 01:43:10 +02:00
endpoint . rtts . Reset ( ) ;
//}
2018-11-18 00:36:55 +01:00
}
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
lastUdpPingTime = 0 ;
if ( proxyProtocol = = PROXY_SOCKS5 )
2019-04-15 01:43:10 +02:00
InitUDPProxy ( ) ;
2020-01-22 12:43:51 +01:00
if ( allowP2p & & currentEndpoint )
{
2019-04-15 01:43:10 +02:00
SendPublicEndpointsRequest ( ) ;
}
BufferOutputStream s ( 4 ) ;
s . WriteInt32 ( dataSavingMode ? INIT_FLAG_DATA_SAVING_ENABLED : 0 ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion < 6 )
{
2019-04-15 01:43:10 +02:00
SendPacketReliably ( PKT_NETWORK_CHANGED , s . GetBuffer ( ) , s . GetLength ( ) , 1 , 20 ) ;
2020-01-22 12:43:51 +01:00
}
else
{
2019-04-15 01:43:10 +02:00
Buffer buf ( move ( s ) ) ;
SendExtra ( buf , EXTRA_TYPE_NETWORK_CHANGED ) ;
}
2020-01-22 12:43:51 +01:00
needReInitUdpProxy = true ;
2019-04-15 01:43:10 +02:00
selectCanceller - > CancelSelect ( ) ;
2020-01-22 12:43:51 +01:00
didSendIPv6Endpoint = false ;
2018-11-18 00:36:55 +01:00
2019-04-15 01:43:10 +02:00
AddIPv6Relays ( ) ;
ResetUdpAvailability ( ) ;
ResetEndpointPingStats ( ) ;
} ) ;
2018-11-18 00:36:55 +01:00
}
}
2020-01-22 12:43:51 +01:00
double VoIPController : : GetAverageRTT ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
if ( lastSentSeq > = lastRemoteAckSeq )
{
uint32_t diff = lastSentSeq - lastRemoteAckSeq ;
2018-11-18 00:36:55 +01:00
//LOGV("rtt diff=%u", diff);
2020-01-22 12:43:51 +01:00
if ( diff < 32 )
{
double res = 0 ;
int count = 0 ;
for ( auto itr = recentOutgoingPackets . begin ( ) ; itr ! = recentOutgoingPackets . end ( ) ; + + itr )
{
if ( itr - > ackTime > 0 )
{
res + = ( itr - > ackTime - itr - > sendTime ) ;
2018-11-18 00:36:55 +01:00
count + + ;
}
}
2020-01-22 12:43:51 +01:00
if ( count > 0 )
res / = count ;
2018-11-18 00:36:55 +01:00
return res ;
}
}
return 999 ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetMicMute ( bool mute )
{
if ( micMuted = = mute )
2018-11-18 00:36:55 +01:00
return ;
2020-01-22 12:43:51 +01:00
micMuted = mute ;
if ( audioInput )
{
if ( mute )
2018-11-18 00:36:55 +01:00
audioInput - > Stop ( ) ;
else
audioInput - > Start ( ) ;
2020-01-22 12:43:51 +01:00
if ( ! audioInput - > IsInitialized ( ) )
{
lastError = ERROR_AUDIO_IO ;
2018-11-18 00:36:55 +01:00
SetState ( STATE_FAILED ) ;
return ;
}
}
2020-01-22 12:43:51 +01:00
if ( echoCanceller )
2018-11-18 00:36:55 +01:00
echoCanceller - > Enable ( ! mute ) ;
2020-01-22 12:43:51 +01:00
if ( state = = STATE_ESTABLISHED )
{
messageThread . Post ( [ this ] {
for ( shared_ptr < Stream > & s : outgoingStreams )
{
if ( s - > type = = STREAM_TYPE_AUDIO )
{
s - > enabled = ! micMuted ;
if ( peerVersion < 6 )
{
2019-04-15 01:43:10 +02:00
unsigned char buf [ 2 ] ;
2020-01-22 12:43:51 +01:00
buf [ 0 ] = s - > id ;
buf [ 1 ] = ( char ) ( micMuted ? 0 : 1 ) ;
2019-04-15 01:43:10 +02:00
SendPacketReliably ( PKT_STREAM_STATE , buf , 2 , .5f , 20 ) ;
2020-01-22 12:43:51 +01:00
}
else
{
2019-04-15 01:43:10 +02:00
SendStreamFlags ( * s ) ;
}
2018-11-18 00:36:55 +01:00
}
}
2019-04-15 01:43:10 +02:00
} ) ;
2018-11-18 00:36:55 +01:00
}
}
2020-01-22 12:43:51 +01:00
string VoIPController : : GetDebugString ( )
{
string r = " Remote endpoints: \n " ;
2018-11-18 00:36:55 +01:00
char buffer [ 2048 ] ;
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & endpoint = _e . second ;
const char * type ;
switch ( endpoint . type )
{
case Endpoint : : Type : : UDP_P2P_INET :
type = " UDP_P2P_INET " ;
break ;
case Endpoint : : Type : : UDP_P2P_LAN :
type = " UDP_P2P_LAN " ;
break ;
case Endpoint : : Type : : UDP_RELAY :
type = " UDP_RELAY " ;
break ;
case Endpoint : : Type : : TCP_RELAY :
type = " TCP_RELAY " ;
break ;
default :
type = " UNKNOWN " ;
break ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
snprintf ( buffer , sizeof ( buffer ) , " %s:%u %dms %d 0x% " PRIx64 " [%s%s] \n " , endpoint . address . IsEmpty ( ) ? ( " [ " + endpoint . v6address . ToString ( ) + " ] " ) . c_str ( ) : endpoint . address . ToString ( ) . c_str ( ) , endpoint . port , ( int ) ( endpoint . averageRTT * 1000 ) , endpoint . udpPongCount , ( uint64_t ) endpoint . id , type , currentEndpoint = = endpoint . id ? " , IN_USE " : " " ) ;
r + = buffer ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
if ( shittyInternetMode )
{
snprintf ( buffer , sizeof ( buffer ) , " ShittyInternetMode: level %u \n " , extraEcLevel ) ;
r + = buffer ;
2018-11-18 00:36:55 +01:00
}
double avgLate [ 3 ] ;
2020-01-22 12:43:51 +01:00
shared_ptr < Stream > stm = GetStreamByType ( STREAM_TYPE_AUDIO , false ) ;
2018-11-18 00:36:55 +01:00
shared_ptr < JitterBuffer > jitterBuffer ;
2020-01-22 12:43:51 +01:00
if ( stm )
jitterBuffer = stm - > jitterBuffer ;
if ( jitterBuffer )
2018-11-18 00:36:55 +01:00
jitterBuffer - > GetAverageLateCount ( avgLate ) ;
else
2020-01-22 12:43:51 +01:00
memset ( avgLate , 0 , 3 * sizeof ( double ) ) ;
2018-11-18 00:36:55 +01:00
snprintf ( buffer , sizeof ( buffer ) ,
" Jitter buffer: %d/%.2f | %.1f, %.1f, %.1f \n "
" RTT avg/min: %d/%d \n "
" Congestion window: %d/%d bytes \n "
" Key fingerprint: %02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%s \n "
" Last sent/ack'd seq: %u/%u \n "
" Last recvd seq: %u \n "
" Send/recv losses: %u/%u (%d%%) \n "
" Audio bitrate: %d kbit \n "
" Outgoing queue: %u \n "
// "Packet grouping: %d\n"
" Frame size out/in: %d/%d \n "
" Bytes sent/recvd: %llu/%llu " ,
jitterBuffer ? jitterBuffer - > GetMinPacketCount ( ) : 0 , jitterBuffer ? jitterBuffer - > GetAverageDelay ( ) : 0 , avgLate [ 0 ] , avgLate [ 1 ] , avgLate [ 2 ] ,
2020-01-22 12:43:51 +01:00
// (int)(GetAverageRTT()*1000), 0,
( int ) ( conctl - > GetAverageRTT ( ) * 1000 ) , ( int ) ( conctl - > GetMinimumRTT ( ) * 1000 ) ,
2018-11-18 00:36:55 +01:00
int ( conctl - > GetInflightDataSize ( ) ) , int ( conctl - > GetCongestionWindow ( ) ) ,
2020-01-22 12:43:51 +01:00
keyFingerprint [ 0 ] , keyFingerprint [ 1 ] , keyFingerprint [ 2 ] , keyFingerprint [ 3 ] , keyFingerprint [ 4 ] , keyFingerprint [ 5 ] , keyFingerprint [ 6 ] , keyFingerprint [ 7 ] ,
2018-11-18 00:36:55 +01:00
useMTProto2 ? " (MTProto2.0) " : " " ,
lastSentSeq , lastRemoteAckSeq , lastRemoteSeq ,
2019-04-15 01:43:10 +02:00
sendLosses , recvLossCount , encoder ? encoder - > GetPacketLoss ( ) : 0 ,
2020-01-22 12:43:51 +01:00
encoder ? ( encoder - > GetBitrate ( ) / 1000 ) : 0 ,
2018-11-18 00:36:55 +01:00
static_cast < unsigned int > ( unsentStreamPackets ) ,
2020-01-22 12:43:51 +01:00
// audioPacketGrouping,
outgoingStreams [ 0 ] - > frameDuration , incomingStreams . size ( ) > 0 ? incomingStreams [ 0 ] - > frameDuration : 0 ,
( long long unsigned int ) ( stats . bytesSentMobile + stats . bytesSentWifi ) ,
( long long unsigned int ) ( stats . bytesRecvdMobile + stats . bytesRecvdWifi ) ) ;
r + = buffer ;
if ( config . enableVideoSend )
{
shared_ptr < Stream > vstm = GetStreamByType ( STREAM_TYPE_VIDEO , true ) ;
if ( vstm & & vstm - > enabled & & videoPacketSender )
{
2019-04-15 01:43:10 +02:00
snprintf ( buffer , sizeof ( buffer ) , " \n Video out: %ux%u '%c%c%c%c' %u kbit " , vstm - > width , vstm - > height , PRINT_FOURCC ( vstm - > codec ) , videoPacketSender - > GetBitrate ( ) ) ;
2020-01-22 12:43:51 +01:00
r + = buffer ;
2019-04-15 01:43:10 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( ! peerVideoDecoders . empty ( ) )
{
r + = " \n Peer codecs: " ;
for ( uint32_t codec : peerVideoDecoders )
{
2019-04-15 01:43:10 +02:00
snprintf ( buffer , sizeof ( buffer ) , " '%c%c%c%c' " , PRINT_FOURCC ( codec ) ) ;
2020-01-22 12:43:51 +01:00
r + = buffer ;
2019-04-15 01:43:10 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( config . enableVideoReceive )
{
shared_ptr < Stream > vstm = GetStreamByType ( STREAM_TYPE_VIDEO , false ) ;
if ( vstm & & vstm - > enabled )
{
2019-04-15 01:43:10 +02:00
snprintf ( buffer , sizeof ( buffer ) , " \n Video in: %ux%u '%c%c%c%c' " , vstm - > width , vstm - > height , PRINT_FOURCC ( vstm - > codec ) ) ;
2020-01-22 12:43:51 +01:00
r + = buffer ;
2019-04-15 01:43:10 +02:00
}
}
2018-11-18 00:36:55 +01:00
return r ;
}
2020-01-22 12:43:51 +01:00
const char * VoIPController : : GetVersion ( )
{
2018-11-18 00:36:55 +01:00
return LIBTGVOIP_VERSION ;
}
2020-01-22 12:43:51 +01:00
int64_t VoIPController : : GetPreferredRelayID ( )
{
2018-11-18 00:36:55 +01:00
return preferredRelay ;
}
2020-01-22 12:43:51 +01:00
int VoIPController : : GetLastError ( )
{
2018-11-18 00:36:55 +01:00
return lastError ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : GetStats ( TrafficStats * stats )
{
2018-11-18 00:36:55 +01:00
memcpy ( stats , & this - > stats , sizeof ( TrafficStats ) ) ;
}
2020-01-22 12:43:51 +01:00
string VoIPController : : GetDebugLog ( )
{
2018-11-29 01:03:15 +01:00
map < string , json11 : : Json > network {
2020-01-22 12:43:51 +01:00
{ " type " , NetworkTypeToString ( networkType ) } } ;
if ( IS_MOBILE_NETWORK ( networkType ) )
{
CellularCarrierInfo carrier = GetCarrierInfo ( ) ;
if ( ! carrier . name . empty ( ) )
{
network [ " carrier " ] = carrier . name ;
network [ " country " ] = carrier . countryCode ;
network [ " mcc " ] = carrier . mcc ;
network [ " mnc " ] = carrier . mnc ;
}
}
else if ( networkType = = NET_TYPE_WIFI )
{
2019-02-11 17:01:45 +01:00
# ifdef __ANDROID__
2020-01-22 12:43:51 +01:00
jni : : DoWithJNI ( [ & ] ( JNIEnv * env ) {
jmethodID getWifiInfoMethod = env - > GetStaticMethodID ( jniUtilitiesClass , " getWifiInfo " , " ()[I " ) ;
jintArray res = static_cast < jintArray > ( env - > CallStaticObjectMethod ( jniUtilitiesClass , getWifiInfoMethod ) ) ;
if ( res )
{
jint * wifiInfo = env - > GetIntArrayElements ( res , NULL ) ;
network [ " rssi " ] = wifiInfo [ 0 ] ;
network [ " link_speed " ] = wifiInfo [ 1 ] ;
2019-02-11 17:01:45 +01:00
env - > ReleaseIntArrayElements ( res , wifiInfo , JNI_ABORT ) ;
}
} ) ;
# endif
}
/*vector<json11::Json> lpkts;
for ( DebugLoggedPacket & lpkt : debugLoggedPackets ) {
lpkts . push_back ( json11 : : Json : : array { lpkt . timestamp , lpkt . seq , lpkt . length } ) ;
2018-11-29 01:03:15 +01:00
}
return json11 : : Json ( json11 : : Json : : object {
{ " log_type " , " out_packet_stats " } ,
{ " libtgvoip_version " , LIBTGVOIP_VERSION } ,
{ " network " , network } ,
{ " protocol_version " , std : : min ( peerVersion , PROTOCOL_VERSION ) } ,
{ " total_losses " , json11 : : Json : : object {
{ " s " , ( int32_t ) conctl - > GetSendLossCount ( ) } ,
{ " r " , ( int32_t ) recvLossCount }
} } ,
{ " call_duration " , GetCurrentTime ( ) - connectionInitTime } ,
{ " out_packet_stats " , lpkts }
2019-02-11 17:01:45 +01:00
} ) . dump ( ) ; */
2019-04-15 01:43:10 +02:00
vector < json11 : : Json > _endpoints ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
2019-04-15 01:43:10 +02:00
string type ;
map < string , json11 : : Json > je {
2020-01-22 12:43:51 +01:00
{ " rtt " , ( int ) ( e . averageRTT * 1000.0 ) } } ;
int64_t id = 0 ;
if ( e . type = = Endpoint : : Type : : UDP_RELAY )
{
je [ " type " ] = e . IsIPv6Only ( ) ? " udp_relay6 " : " udp_relay " ;
id = e . CleanID ( ) ;
if ( e . totalUdpPings = = 0 )
je [ " udp_pings " ] = 0.0 ;
2019-04-15 01:43:10 +02:00
else
2020-01-22 12:43:51 +01:00
je [ " udp_pings " ] = ( double ) e . totalUdpPingReplies / ( double ) e . totalUdpPings ;
je [ " self_rtt " ] = ( int ) ( e . selfRtts . Average ( ) * 1000.0 ) ;
}
else if ( e . type = = Endpoint : : Type : : TCP_RELAY )
{
je [ " type " ] = e . IsIPv6Only ( ) ? " tcp_relay6 " : " tcp_relay " ;
id = e . CleanID ( ) ;
}
else if ( e . type = = Endpoint : : Type : : UDP_P2P_INET )
{
je [ " type " ] = e . IsIPv6Only ( ) ? " p2p_inet6 " : " p2p_inet " ;
}
else if ( e . type = = Endpoint : : Type : : UDP_P2P_LAN )
{
je [ " type " ] = " p2p_lan " ;
}
if ( preferredRelay = = e . id & & wasEstablished )
je [ " pref " ] = true ;
if ( id )
{
2019-04-15 01:43:10 +02:00
ostringstream s ;
s < < id ;
2020-01-22 12:43:51 +01:00
je [ " id " ] = s . str ( ) ;
2019-04-15 01:43:10 +02:00
}
_endpoints . push_back ( je ) ;
}
2020-01-22 12:43:51 +01:00
string p2pType = " none " ;
Endpoint & cur = endpoints [ currentEndpoint ] ;
if ( cur . type = = Endpoint : : Type : : UDP_P2P_INET )
p2pType = cur . IsIPv6Only ( ) ? " inet6 " : " inet " ;
else if ( cur . type = = Endpoint : : Type : : UDP_P2P_LAN )
p2pType = " lan " ;
2019-02-11 17:01:45 +01:00
vector < string > problems ;
2020-01-22 12:43:51 +01:00
if ( lastError = = ERROR_TIMEOUT )
2019-02-11 17:01:45 +01:00
problems . push_back ( " timeout " ) ;
2020-01-22 12:43:51 +01:00
if ( wasReconnecting )
2019-02-11 17:01:45 +01:00
problems . push_back ( " reconnecting " ) ;
2020-01-22 12:43:51 +01:00
if ( wasExtraEC )
2019-02-11 17:01:45 +01:00
problems . push_back ( " extra_ec " ) ;
2020-01-22 12:43:51 +01:00
if ( wasEncoderLaggy )
2019-02-11 17:01:45 +01:00
problems . push_back ( " encoder_lag " ) ;
2020-01-22 12:43:51 +01:00
if ( ! wasEstablished )
2019-02-11 17:01:45 +01:00
problems . push_back ( " not_inited " ) ;
2020-01-22 12:43:51 +01:00
if ( wasNetworkHandover )
2019-02-11 17:01:45 +01:00
problems . push_back ( " network_handover " ) ;
return json11 : : Json ( json11 : : Json : : object {
2020-01-22 12:43:51 +01:00
{ " log_type " , " call_stats " } ,
{ " libtgvoip_version " , LIBTGVOIP_VERSION } ,
{ " network " , network } ,
{ " protocol_version " , std : : min ( peerVersion , PROTOCOL_VERSION ) } ,
{ " udp_avail " , udpConnectivityState = = UDP_AVAILABLE } ,
{ " tcp_used " , useTCP } ,
{ " p2p_type " , p2pType } ,
{ " packet_stats " , json11 : : Json : : object {
{ " out " , ( int ) seq } ,
{ " in " , ( int ) packetsReceived } ,
{ " lost_out " , ( int ) conctl - > GetSendLossCount ( ) } ,
{ " lost_in " , ( int ) recvLossCount } } } ,
{ " endpoints " , _endpoints } ,
{ " problems " , problems } } )
. dump ( ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
vector < AudioInputDevice > VoIPController : : EnumerateAudioInputs ( )
{
2018-11-18 00:36:55 +01:00
vector < AudioInputDevice > devs ;
audio : : AudioInput : : EnumerateDevices ( devs ) ;
return devs ;
}
2020-01-22 12:43:51 +01:00
vector < AudioOutputDevice > VoIPController : : EnumerateAudioOutputs ( )
{
2018-11-18 00:36:55 +01:00
vector < AudioOutputDevice > devs ;
audio : : AudioOutput : : EnumerateDevices ( devs ) ;
return devs ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetCurrentAudioInput ( string id )
{
currentAudioInput = id ;
if ( audioInput )
2018-11-18 00:36:55 +01:00
audioInput - > SetCurrentDevice ( id ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetCurrentAudioOutput ( string id )
{
currentAudioOutput = id ;
if ( audioOutput )
2018-11-18 00:36:55 +01:00
audioOutput - > SetCurrentDevice ( id ) ;
}
2020-01-22 12:43:51 +01:00
string VoIPController : : GetCurrentAudioInputID ( )
{
2018-11-18 00:36:55 +01:00
return currentAudioInput ;
}
2020-01-22 12:43:51 +01:00
string VoIPController : : GetCurrentAudioOutputID ( )
{
2018-11-18 00:36:55 +01:00
return currentAudioOutput ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetProxy ( int protocol , string address , uint16_t port , string username , string password )
{
proxyProtocol = protocol ;
proxyAddress = std : : move ( address ) ;
proxyPort = port ;
proxyUsername = std : : move ( username ) ;
proxyPassword = std : : move ( password ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
int VoIPController : : GetSignalBarsCount ( )
{
2018-11-18 00:36:55 +01:00
return signalBarsHistory . NonZeroAverage ( ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetCallbacks ( VoIPController : : Callbacks callbacks )
{
this - > callbacks = callbacks ;
if ( callbacks . connectionStateChanged )
2018-11-18 00:36:55 +01:00
callbacks . connectionStateChanged ( this , state ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetAudioOutputGainControlEnabled ( bool enabled )
{
2018-11-18 00:36:55 +01:00
LOGD ( " New output AGC state: %d " , enabled ) ;
}
2020-01-22 12:43:51 +01:00
uint32_t VoIPController : : GetPeerCapabilities ( )
{
2018-11-18 00:36:55 +01:00
return peerCapabilities ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendGroupCallKey ( unsigned char * key )
{
2018-11-18 00:36:55 +01:00
Buffer buf ( 256 ) ;
buf . CopyFrom ( key , 0 , 256 ) ;
2020-01-22 12:43:51 +01:00
shared_ptr < Buffer > keyPtr = make_shared < Buffer > ( move ( buf ) ) ;
messageThread . Post ( [ this , keyPtr ] {
if ( ! ( peerCapabilities & TGVOIP_PEER_CAP_GROUP_CALLS ) )
{
2019-04-15 01:43:10 +02:00
LOGE ( " Tried to send group call key but peer isn't capable of them " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( didSendGroupCallKey )
{
2019-04-15 01:43:10 +02:00
LOGE ( " Tried to send a group call key repeatedly " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( ! isOutgoing )
{
2019-04-15 01:43:10 +02:00
LOGE ( " You aren't supposed to send group call key in an incoming call, use VoIPController::RequestCallUpgrade() instead " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
didSendGroupCallKey = true ;
2019-04-15 01:43:10 +02:00
SendExtra ( * keyPtr , EXTRA_TYPE_GROUP_CALL_KEY ) ;
} ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : RequestCallUpgrade ( )
{
messageThread . Post ( [ this ] {
if ( ! ( peerCapabilities & TGVOIP_PEER_CAP_GROUP_CALLS ) )
{
2019-04-15 01:43:10 +02:00
LOGE ( " Tried to send group call key but peer isn't capable of them " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( didSendUpgradeRequest )
{
2019-04-15 01:43:10 +02:00
LOGE ( " Tried to send upgrade request repeatedly " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( isOutgoing )
{
2019-04-15 01:43:10 +02:00
LOGE ( " You aren't supposed to send an upgrade request in an outgoing call, generate an encryption key and use VoIPController::SendGroupCallKey instead " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
didSendUpgradeRequest = true ;
2019-04-15 01:43:10 +02:00
Buffer empty ( 0 ) ;
SendExtra ( empty , EXTRA_TYPE_REQUEST_GROUP ) ;
} ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetEchoCancellationStrength ( int strength )
{
echoCancellationStrength = strength ;
if ( echoCanceller )
2018-11-18 00:36:55 +01:00
echoCanceller - > SetAECStrength ( strength ) ;
}
# if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
2020-01-22 12:43:51 +01:00
void VoIPController : : SetAudioDataCallbacks ( std : : function < void ( int16_t * , size_t ) > input , std : : function < void ( int16_t * , size_t ) > output , std : : function < void ( int16_t * , size_t ) > preproc = nullptr )
{
audioInputDataCallback = input ;
audioOutputDataCallback = output ;
audioPreprocDataCallback = preproc ;
preprocDecoder = preprocDecoder ? preprocDecoder : opus_decoder_create ( 48000 , 1 , NULL ) ;
2018-11-18 00:36:55 +01:00
}
# endif
2020-01-22 12:43:51 +01:00
int VoIPController : : GetConnectionState ( )
{
2018-11-18 00:36:55 +01:00
return state ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetConfig ( const Config & cfg )
{
config = cfg ;
if ( tgvoipLogFile )
{
2018-11-18 00:36:55 +01:00
fclose ( tgvoipLogFile ) ;
2020-01-22 12:43:51 +01:00
tgvoipLogFile = NULL ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
if ( ! config . logFilePath . empty ( ) )
{
2018-11-18 00:36:55 +01:00
# ifndef _WIN32
2020-01-22 12:43:51 +01:00
tgvoipLogFile = fopen ( config . logFilePath . c_str ( ) , " a " ) ;
2018-11-18 00:36:55 +01:00
# else
2020-01-22 12:43:51 +01:00
if ( _wfopen_s ( & tgvoipLogFile , config . logFilePath . c_str ( ) , L " a " ) ! = 0 )
{
tgvoipLogFile = NULL ;
2018-11-18 00:36:55 +01:00
}
# endif
tgvoip_log_file_write_header ( tgvoipLogFile ) ;
}
2020-01-22 12:43:51 +01:00
else
{
tgvoipLogFile = NULL ;
}
if ( statsDump )
{
2018-11-18 00:36:55 +01:00
fclose ( statsDump ) ;
2020-01-22 12:43:51 +01:00
statsDump = NULL ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
if ( ! config . statsDumpFilePath . empty ( ) )
{
2018-11-18 00:36:55 +01:00
# ifndef _WIN32
2020-01-22 12:43:51 +01:00
statsDump = fopen ( config . statsDumpFilePath . c_str ( ) , " w " ) ;
2018-11-18 00:36:55 +01:00
# else
2020-01-22 12:43:51 +01:00
if ( _wfopen_s ( & statsDump , config . statsDumpFilePath . c_str ( ) , L " w " ) ! = 0 )
{
statsDump = NULL ;
2018-11-18 00:36:55 +01:00
}
# endif
2020-01-22 12:43:51 +01:00
if ( statsDump )
2018-11-18 00:36:55 +01:00
fprintf ( statsDump , " Time \t RTT \t LRSeq \t LSSeq \t LASeq \t LostR \t LostS \t CWnd \t Bitrate \t Loss%% \t Jitter \t JDelay \t AJDelay \n " ) ;
//else
// LOGW("Failed to open stats dump file %s for writing", config.statsDumpFilePath.c_str());
2020-01-22 12:43:51 +01:00
}
else
{
statsDump = NULL ;
2018-11-18 00:36:55 +01:00
}
UpdateDataSavingState ( ) ;
UpdateAudioBitrateLimit ( ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetPersistentState ( vector < uint8_t > state )
{
2018-12-19 17:51:45 +01:00
using namespace json11 ;
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
if ( state . empty ( ) )
2018-12-19 17:51:45 +01:00
return ;
string jsonErr ;
2020-01-22 12:43:51 +01:00
string json = string ( state . begin ( ) , state . end ( ) ) ;
Json _obj = Json : : parse ( json , jsonErr ) ;
if ( ! jsonErr . empty ( ) )
{
2018-12-19 17:51:45 +01:00
LOGE ( " Error parsing persistable state: %s " , jsonErr . c_str ( ) ) ;
return ;
}
2020-01-22 12:43:51 +01:00
Json : : object obj = _obj . object_items ( ) ;
if ( obj . find ( " proxy " ) ! = obj . end ( ) )
{
Json : : object proxy = obj [ " proxy " ] . object_items ( ) ;
lastTestedProxyServer = proxy [ " server " ] . string_value ( ) ;
proxySupportsUDP = proxy [ " udp " ] . bool_value ( ) ;
proxySupportsTCP = proxy [ " tcp " ] . bool_value ( ) ;
2018-12-19 17:51:45 +01:00
}
}
2020-01-22 12:43:51 +01:00
vector < uint8_t > VoIPController : : GetPersistentState ( )
{
2018-12-19 17:51:45 +01:00
using namespace json11 ;
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
Json : : object obj = Json : : object {
2018-12-19 17:51:45 +01:00
{ " ver " , 1 } ,
} ;
2020-01-22 12:43:51 +01:00
if ( proxyProtocol = = PROXY_SOCKS5 )
{
2018-12-19 17:51:45 +01:00
char pbuf [ 128 ] ;
snprintf ( pbuf , sizeof ( pbuf ) , " %s:%u " , proxyAddress . c_str ( ) , proxyPort ) ;
2020-01-22 12:43:51 +01:00
obj . insert ( { " proxy " , Json : : object {
{ " server " , string ( pbuf ) } ,
{ " udp " , proxySupportsUDP } ,
{ " tcp " , proxySupportsTCP } } } ) ;
}
string _jstr = Json ( obj ) . dump ( ) ;
const char * jstr = _jstr . c_str ( ) ;
return vector < uint8_t > ( jstr , jstr + strlen ( jstr ) ) ;
2018-12-19 17:51:45 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetOutputVolume ( float level )
{
2018-12-30 00:24:55 +01:00
outputVolume . SetLevel ( level ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetInputVolume ( float level )
{
2018-12-30 00:24:55 +01:00
inputVolume . SetLevel ( level ) ;
}
2018-12-31 16:27:00 +01:00
# if defined(__APPLE__) && TARGET_OS_OSX
2020-01-22 12:43:51 +01:00
void VoIPController : : SetAudioOutputDuckingEnabled ( bool enabled )
{
macAudioDuckingEnabled = enabled ;
audio : : AudioUnitIO * osxAudio = dynamic_cast < audio : : AudioUnitIO * > ( audioIO ) ;
if ( osxAudio )
{
2018-12-30 00:24:55 +01:00
osxAudio - > SetDuckingEnabled ( enabled ) ;
}
}
# endif
2018-11-18 00:36:55 +01:00
# pragma mark - Internal intialization
2020-01-22 12:43:51 +01:00
void VoIPController : : InitializeTimers ( )
{
initTimeoutID = messageThread . Post ( [ this ] {
2018-11-18 00:36:55 +01:00
LOGW ( " Init timeout, disconnecting " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_TIMEOUT ;
2018-11-18 00:36:55 +01:00
SetState ( STATE_FAILED ) ;
2020-01-22 12:43:51 +01:00
} ,
config . initTimeout ) ;
2018-11-18 00:36:55 +01:00
2020-01-22 12:43:51 +01:00
if ( ! config . statsDumpFilePath . empty ( ) )
{
messageThread . Post ( [ this ] {
if ( statsDump & & incomingStreams . size ( ) = = 1 )
{
shared_ptr < JitterBuffer > & jitterBuffer = incomingStreams [ 0 ] - > jitterBuffer ;
2018-11-18 00:36:55 +01:00
//fprintf(statsDump, "Time\tRTT\tLISeq\tLASeq\tCWnd\tBitrate\tJitter\tJDelay\tAJDelay\n");
fprintf ( statsDump , " %.3f \t %.3f \t %d \t %d \t %d \t %d \t %d \t %d \t %d \t %d \t %.3f \t %.3f \t %.3f \n " ,
2020-01-22 12:43:51 +01:00
GetCurrentTime ( ) - connectionInitTime ,
2018-11-18 00:36:55 +01:00
endpoints . at ( currentEndpoint ) . rtts [ 0 ] ,
lastRemoteSeq ,
2019-02-05 12:41:00 +01:00
( uint32_t ) seq ,
2018-11-18 00:36:55 +01:00
lastRemoteAckSeq ,
recvLossCount ,
conctl ? conctl - > GetSendLossCount ( ) : 0 ,
conctl ? ( int ) conctl - > GetInflightDataSize ( ) : 0 ,
encoder ? encoder - > GetBitrate ( ) : 0 ,
encoder ? encoder - > GetPacketLoss ( ) : 0 ,
jitterBuffer ? jitterBuffer - > GetLastMeasuredJitter ( ) : 0 ,
2020-01-22 12:43:51 +01:00
jitterBuffer ? jitterBuffer - > GetLastMeasuredDelay ( ) * 0.06 : 0 ,
jitterBuffer ? jitterBuffer - > GetAverageDelay ( ) * 0.06 : 0 ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
} ,
0.1 , 0.1 ) ;
2018-11-18 00:36:55 +01:00
}
messageThread . Post ( std : : bind ( & VoIPController : : SendRelayPings , this ) , 0.0 , 2.0 ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : RunSendThread ( )
{
2018-11-18 00:36:55 +01:00
InitializeAudio ( ) ;
InitializeTimers ( ) ;
2019-04-15 01:43:10 +02:00
messageThread . Post ( bind ( & VoIPController : : SendInit , this ) ) ;
2020-01-22 12:43:51 +01:00
while ( true )
{
RawPendingOutgoingPacket pkt = rawSendQueue . GetBlocking ( ) ;
if ( pkt . packet . IsEmpty ( ) )
2019-04-15 01:43:10 +02:00
break ;
2020-01-22 12:43:51 +01:00
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesSentMobile + = ( uint64_t ) pkt . packet . data . Length ( ) ;
2019-04-15 01:43:10 +02:00
else
2020-01-22 12:43:51 +01:00
stats . bytesSentWifi + = ( uint64_t ) pkt . packet . data . Length ( ) ;
if ( pkt . packet . protocol = = NetworkProtocol : : TCP )
{
if ( pkt . socket & & ! pkt . socket - > IsFailed ( ) )
{
2019-04-15 01:43:10 +02:00
pkt . socket - > Send ( std : : move ( pkt . packet ) ) ;
}
2020-01-22 12:43:51 +01:00
}
else
{
2019-04-15 01:43:10 +02:00
udpSocket - > Send ( std : : move ( pkt . packet ) ) ;
}
}
2018-11-18 00:36:55 +01:00
LOGI ( " === send thread exiting === " ) ;
}
# pragma mark - Miscellaneous
2020-01-22 12:43:51 +01:00
void VoIPController : : SetState ( int state )
{
this - > state = state ;
2018-11-18 00:36:55 +01:00
LOGV ( " Call state changed to %d " , state ) ;
2020-01-22 12:43:51 +01:00
stateChangeTime = GetCurrentTime ( ) ;
messageThread . Post ( [ this , state ] {
if ( callbacks . connectionStateChanged )
2018-11-18 00:36:55 +01:00
callbacks . connectionStateChanged ( this , state ) ;
} ) ;
2020-01-22 12:43:51 +01:00
if ( state = = STATE_ESTABLISHED )
{
2018-11-18 00:36:55 +01:00
SetMicMute ( micMuted ) ;
2020-01-22 12:43:51 +01:00
if ( ! wasEstablished )
{
wasEstablished = true ;
2018-11-18 00:36:55 +01:00
messageThread . Post ( std : : bind ( & VoIPController : : UpdateRTT , this ) , 0.1 , 0.5 ) ;
messageThread . Post ( std : : bind ( & VoIPController : : UpdateAudioBitrate , this ) , 0.0 , 0.3 ) ;
messageThread . Post ( std : : bind ( & VoIPController : : UpdateCongestion , this ) , 0.0 , 1.0 ) ;
messageThread . Post ( std : : bind ( & VoIPController : : UpdateSignalBars , this ) , 1.0 , 1.0 ) ;
2019-04-15 01:43:10 +02:00
messageThread . Post ( std : : bind ( & VoIPController : : TickJitterBufferAndCongestionControl , this ) , 0.0 , 0.1 ) ;
2018-11-18 00:36:55 +01:00
}
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendStreamFlags ( Stream & stream )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2018-11-18 00:36:55 +01:00
BufferOutputStream s ( 5 ) ;
s . WriteByte ( stream . id ) ;
2020-01-22 12:43:51 +01:00
uint32_t flags = 0 ;
if ( stream . enabled )
flags | = STREAM_FLAG_ENABLED ;
if ( stream . extraECEnabled )
flags | = STREAM_FLAG_EXTRA_EC ;
if ( stream . paused )
flags | = STREAM_FLAG_PAUSED ;
2018-11-18 00:36:55 +01:00
s . WriteInt32 ( flags ) ;
LOGV ( " My stream state: id %u flags %u " , ( unsigned int ) stream . id , ( unsigned int ) flags ) ;
Buffer buf ( move ( s ) ) ;
SendExtra ( buf , EXTRA_TYPE_STREAM_FLAGS ) ;
}
2020-01-22 12:43:51 +01:00
shared_ptr < VoIPController : : Stream > VoIPController : : GetStreamByType ( int type , bool outgoing )
{
2018-11-18 00:36:55 +01:00
shared_ptr < Stream > s ;
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & ss : ( outgoing ? outgoingStreams : incomingStreams ) )
{
if ( ss - > type = = type )
2018-11-18 00:36:55 +01:00
return ss ;
}
return s ;
}
2020-01-22 12:43:51 +01:00
shared_ptr < VoIPController : : Stream > VoIPController : : GetStreamByID ( unsigned char id , bool outgoing )
{
2019-04-15 01:43:10 +02:00
shared_ptr < Stream > s ;
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & ss : ( outgoing ? outgoingStreams : incomingStreams ) )
{
if ( ss - > id = = id )
2019-04-15 01:43:10 +02:00
return ss ;
}
return s ;
}
2020-01-22 12:43:51 +01:00
CellularCarrierInfo VoIPController : : GetCarrierInfo ( )
{
2018-11-29 01:03:15 +01:00
# if defined(__APPLE__) && TARGET_OS_IOS
return DarwinSpecific : : GetCarrierInfo ( ) ;
# elif defined(__ANDROID__)
CellularCarrierInfo carrier ;
2020-01-22 12:43:51 +01:00
jni : : DoWithJNI ( [ & carrier ] ( JNIEnv * env ) {
jmethodID getCarrierInfoMethod = env - > GetStaticMethodID ( jniUtilitiesClass , " getCarrierInfo " , " ()[Ljava/lang/String; " ) ;
jobjectArray jinfo = ( jobjectArray ) env - > CallStaticObjectMethod ( jniUtilitiesClass , getCarrierInfoMethod ) ;
if ( jinfo & & env - > GetArrayLength ( jinfo ) = = 4 )
{
carrier . name = jni : : JavaStringToStdString ( env , ( jstring ) env - > GetObjectArrayElement ( jinfo , 0 ) ) ;
carrier . countryCode = jni : : JavaStringToStdString ( env , ( jstring ) env - > GetObjectArrayElement ( jinfo , 1 ) ) ;
carrier . mcc = jni : : JavaStringToStdString ( env , ( jstring ) env - > GetObjectArrayElement ( jinfo , 2 ) ) ;
carrier . mnc = jni : : JavaStringToStdString ( env , ( jstring ) env - > GetObjectArrayElement ( jinfo , 3 ) ) ;
}
else
{
2018-11-29 01:03:15 +01:00
LOGW ( " Failed to get carrier info " ) ;
}
} ) ;
return carrier ;
# else
return CellularCarrierInfo ( ) ;
# endif
}
2018-11-18 00:36:55 +01:00
# pragma mark - Audio I / O
2020-01-22 12:43:51 +01:00
void VoIPController : : HandleAudioInput ( unsigned char * data , size_t len , unsigned char * secondaryData , size_t secondaryLen )
{
if ( stopping )
2018-11-18 00:36:55 +01:00
return ;
2019-04-15 01:43:10 +02:00
// TODO make an AudioPacketSender
2020-01-22 12:43:51 +01:00
Buffer dataBuf = outgoingAudioBufferPool . Get ( ) ;
Buffer secondaryDataBuf = secondaryLen & & secondaryData ? outgoingAudioBufferPool . Get ( ) : Buffer ( ) ;
2019-04-15 01:43:10 +02:00
dataBuf . CopyFrom ( data , 0 , len ) ;
2020-01-22 12:43:51 +01:00
if ( secondaryLen & & secondaryData )
{
2019-04-15 01:43:10 +02:00
secondaryDataBuf . CopyFrom ( secondaryData , 0 , secondaryLen ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
shared_ptr < Buffer > dataBufPtr = make_shared < Buffer > ( move ( dataBuf ) ) ;
shared_ptr < Buffer > secondaryDataBufPtr = make_shared < Buffer > ( move ( secondaryDataBuf ) ) ;
2018-11-18 00:36:55 +01:00
2020-01-22 12:43:51 +01:00
messageThread . Post ( [ this , dataBufPtr , secondaryDataBufPtr , len , secondaryLen ] ( ) {
2019-04-15 01:43:10 +02:00
unsentStreamPacketsHistory . Add ( static_cast < unsigned int > ( unsentStreamPackets ) ) ;
2020-01-22 12:43:51 +01:00
if ( unsentStreamPacketsHistory . Average ( ) > = maxUnsentStreamPackets & & ! videoPacketSender )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Resetting stalled send queue " ) ;
sendQueue . clear ( ) ;
unsentStreamPacketsHistory . Reset ( ) ;
2020-01-22 12:43:51 +01:00
unsentStreamPackets = 0 ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( waitingForAcks | | dontSendPackets > 0 | | ( ( unsigned int ) unsentStreamPackets > = maxUnsentStreamPackets /*&& endpoints[currentEndpoint].type==Endpoint::Type::TCP_RELAY*/ ) )
{
LOGV ( " waiting for queue, dropping outgoing audio packet, %d %d %d [%d] " , ( unsigned int ) unsentStreamPackets , waitingForAcks , dontSendPackets , maxUnsentStreamPackets ) ;
2019-04-15 01:43:10 +02:00
return ;
}
//LOGV("Audio packet size %u", (unsigned int)len);
2020-01-22 12:43:51 +01:00
if ( ! receivedInitAck )
2019-04-15 01:43:10 +02:00
return ;
2018-11-18 00:36:55 +01:00
2019-04-15 01:43:10 +02:00
BufferOutputStream pkt ( 1500 ) ;
2018-11-18 00:36:55 +01:00
2020-01-22 12:43:51 +01:00
bool hasExtraFEC = peerVersion > = 7 & & secondaryLen & & shittyInternetMode ;
unsigned char flags = ( unsigned char ) ( len > 255 | | hasExtraFEC ? STREAM_DATA_FLAG_LEN16 : 0 ) ;
pkt . WriteByte ( ( unsigned char ) ( 1 | flags ) ) ; // streamID + flags
if ( len > 255 | | hasExtraFEC )
{
int16_t lenAndFlags = static_cast < int16_t > ( len ) ;
if ( hasExtraFEC )
lenAndFlags | = STREAM_DATA_XFLAG_EXTRA_FEC ;
2019-04-15 01:43:10 +02:00
pkt . WriteInt16 ( lenAndFlags ) ;
2020-01-22 12:43:51 +01:00
}
else
{
pkt . WriteByte ( ( unsigned char ) len ) ;
2019-04-15 01:43:10 +02:00
}
2018-11-18 00:36:55 +01:00
pkt . WriteInt32 ( audioTimestampOut ) ;
2019-04-15 01:43:10 +02:00
pkt . WriteBytes ( * dataBufPtr , 0 , len ) ;
2020-01-22 12:43:51 +01:00
if ( hasExtraFEC )
{
2019-04-15 01:43:10 +02:00
Buffer ecBuf ( secondaryLen ) ;
ecBuf . CopyFrom ( * secondaryDataBufPtr , 0 , secondaryLen ) ;
2020-01-22 12:43:51 +01:00
if ( ecAudioPackets . size ( ) = = 4 )
{
ecAudioPackets . pop_front ( ) ;
}
2019-04-15 01:43:10 +02:00
ecAudioPackets . push_back ( move ( ecBuf ) ) ;
2020-01-22 12:43:51 +01:00
uint8_t fecCount = std : : min ( static_cast < uint8_t > ( ecAudioPackets . size ( ) ) , extraEcLevel ) ;
pkt . WriteByte ( fecCount ) ;
for ( auto ecData = ecAudioPackets . end ( ) - fecCount ; ecData ! = ecAudioPackets . end ( ) ; + + ecData )
{
pkt . WriteByte ( ( unsigned char ) ecData - > Length ( ) ) ;
2019-04-15 01:43:10 +02:00
pkt . WriteBytes ( * ecData ) ;
}
2018-11-18 00:36:55 +01:00
}
2019-04-15 01:43:10 +02:00
unsentStreamPackets + + ;
2018-11-18 00:36:55 +01:00
PendingOutgoingPacket p {
2020-01-22 12:43:51 +01:00
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_STREAM_DATA ,
/*.len=*/ pkt . GetLength ( ) ,
/*.data=*/ Buffer ( move ( pkt ) ) ,
/*.endpoint=*/ 0 ,
2018-11-18 00:36:55 +01:00
} ;
2019-04-15 01:43:10 +02:00
conctl - > PacketSent ( p . seq , p . len ) ;
2018-11-18 00:36:55 +01:00
SendOrEnqueuePacket ( move ( p ) ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion < 7 & & secondaryLen & & shittyInternetMode )
{
2019-04-15 01:43:10 +02:00
Buffer ecBuf ( secondaryLen ) ;
ecBuf . CopyFrom ( * secondaryDataBufPtr , 0 , secondaryLen ) ;
2020-01-22 12:43:51 +01:00
if ( ecAudioPackets . size ( ) = = 4 )
{
ecAudioPackets . pop_front ( ) ;
}
2019-04-15 01:43:10 +02:00
ecAudioPackets . push_back ( move ( ecBuf ) ) ;
2020-01-22 12:43:51 +01:00
pkt = BufferOutputStream ( 1500 ) ;
2019-04-15 01:43:10 +02:00
pkt . WriteByte ( outgoingStreams [ 0 ] - > id ) ;
pkt . WriteInt32 ( audioTimestampOut ) ;
2020-01-22 12:43:51 +01:00
uint8_t fecCount = std : : min ( static_cast < uint8_t > ( ecAudioPackets . size ( ) ) , extraEcLevel ) ;
pkt . WriteByte ( fecCount ) ;
for ( auto ecData = ecAudioPackets . end ( ) - fecCount ; ecData ! = ecAudioPackets . end ( ) ; + + ecData )
{
pkt . WriteByte ( ( unsigned char ) ecData - > Length ( ) ) ;
2019-04-15 01:43:10 +02:00
pkt . WriteBytes ( * ecData ) ;
}
2018-11-18 00:36:55 +01:00
2019-04-15 01:43:10 +02:00
PendingOutgoingPacket p {
2020-01-22 12:43:51 +01:00
GenerateOutSeq ( ) ,
PKT_STREAM_EC ,
pkt . GetLength ( ) ,
Buffer ( move ( pkt ) ) ,
0 } ;
2019-04-15 01:43:10 +02:00
SendOrEnqueuePacket ( move ( p ) ) ;
}
2020-01-22 12:43:51 +01:00
audioTimestampOut + = outgoingStreams [ 0 ] - > frameDuration ;
2019-04-15 01:43:10 +02:00
} ) ;
2019-12-24 19:40:50 +01:00
# if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
2020-01-22 12:43:51 +01:00
if ( audioPreprocDataCallback & & preprocDecoder )
{
int size = opus_decode ( preprocDecoder , data , len , preprocBuffer , 4096 , 0 ) ;
audioPreprocDataCallback ( preprocBuffer , size ) ;
2019-12-24 19:40:50 +01:00
}
# endif
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : InitializeAudio ( )
{
double t = GetCurrentTime ( ) ;
shared_ptr < Stream > outgoingAudioStream = GetStreamByType ( STREAM_TYPE_AUDIO , true ) ;
2018-11-18 00:36:55 +01:00
LOGI ( " before create audio io " ) ;
2020-01-22 12:43:51 +01:00
audioIO = audio : : AudioIO : : Create ( currentAudioInput , currentAudioOutput ) ;
audioInput = audioIO - > GetInput ( ) ;
audioOutput = audioIO - > GetOutput ( ) ;
2018-11-21 19:22:31 +01:00
# ifdef __ANDROID__
2020-01-22 12:43:51 +01:00
audio : : AudioInputAndroid * androidInput = dynamic_cast < audio : : AudioInputAndroid * > ( audioInput ) ;
if ( androidInput )
{
unsigned int effects = androidInput - > GetEnabledEffects ( ) ;
if ( ! ( effects & audio : : AudioInputAndroid : : EFFECT_AEC ) )
{
config . enableAEC = true ;
2018-11-21 19:22:31 +01:00
LOGI ( " Forcing software AEC because built-in is not good " ) ;
}
2020-01-22 12:43:51 +01:00
if ( ! ( effects & audio : : AudioInputAndroid : : EFFECT_NS ) )
{
config . enableNS = true ;
2018-11-21 19:22:31 +01:00
LOGI ( " Forcing software NS because built-in is not good " ) ;
}
}
2018-12-31 16:27:00 +01:00
# elif defined(__APPLE__) && TARGET_OS_OSX
2018-12-30 00:24:55 +01:00
SetAudioOutputDuckingEnabled ( macAudioDuckingEnabled ) ;
2018-11-21 19:22:31 +01:00
# endif
2018-11-18 00:36:55 +01:00
LOGI ( " AEC: %d NS: %d AGC: %d " , config . enableAEC , config . enableNS , config . enableAGC ) ;
2020-01-22 12:43:51 +01:00
echoCanceller = new EchoCanceller ( config . enableAEC , config . enableNS , config . enableAGC ) ;
encoder = new OpusEncoder ( audioInput , true ) ;
2019-04-15 01:43:10 +02:00
encoder - > SetCallback ( bind ( & VoIPController : : HandleAudioInput , this , placeholders : : _1 , placeholders : : _2 , placeholders : : _3 , placeholders : : _4 ) ) ;
2018-11-18 00:36:55 +01:00
encoder - > SetOutputFrameDuration ( outgoingAudioStream - > frameDuration ) ;
encoder - > SetEchoCanceller ( echoCanceller ) ;
encoder - > SetSecondaryEncoderEnabled ( false ) ;
2020-01-22 12:43:51 +01:00
if ( config . enableVolumeControl )
{
2018-12-30 00:24:55 +01:00
encoder - > AddAudioEffect ( & inputVolume ) ;
}
2018-11-18 00:36:55 +01:00
# if defined(TGVOIP_USE_CALLBACK_AUDIO_IO)
2020-01-22 12:43:51 +01:00
dynamic_cast < audio : : AudioInputCallback * > ( audioInput ) - > SetDataCallback ( audioInputDataCallback ) ;
dynamic_cast < audio : : AudioOutputCallback * > ( audioOutput ) - > SetDataCallback ( audioOutputDataCallback ) ;
2018-11-18 00:36:55 +01:00
# endif
2020-01-22 12:43:51 +01:00
if ( ! audioOutput - > IsInitialized ( ) )
{
2018-11-21 19:22:31 +01:00
LOGE ( " Error initializing audio playback " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_AUDIO_IO ;
2018-11-18 00:36:55 +01:00
SetState ( STATE_FAILED ) ;
return ;
}
UpdateAudioBitrateLimit ( ) ;
2020-01-22 12:43:51 +01:00
LOGI ( " Audio initialization took %f seconds " , GetCurrentTime ( ) - t ) ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : StartAudio ( )
{
2018-11-18 00:36:55 +01:00
OnAudioOutputReady ( ) ;
encoder - > Start ( ) ;
2020-01-22 12:43:51 +01:00
if ( ! micMuted )
{
2018-11-18 00:36:55 +01:00
audioInput - > Start ( ) ;
2020-01-22 12:43:51 +01:00
if ( ! audioInput - > IsInitialized ( ) )
{
2019-04-15 01:43:10 +02:00
LOGE ( " Error initializing audio capture " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_AUDIO_IO ;
2018-11-18 00:36:55 +01:00
SetState ( STATE_FAILED ) ;
return ;
}
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : OnAudioOutputReady ( )
{
2018-11-18 00:36:55 +01:00
LOGI ( " Audio I/O ready " ) ;
2020-01-22 12:43:51 +01:00
auto & stm = incomingStreams [ 0 ] ;
stm - > decoder = make_shared < OpusDecoder > ( audioOutput , true , peerVersion > = 6 ) ;
2018-11-18 00:36:55 +01:00
stm - > decoder - > SetEchoCanceller ( echoCanceller ) ;
2020-01-22 12:43:51 +01:00
if ( config . enableVolumeControl )
{
2018-12-30 00:24:55 +01:00
stm - > decoder - > AddAudioEffect ( & outputVolume ) ;
}
2018-11-18 00:36:55 +01:00
stm - > decoder - > SetJitterBuffer ( stm - > jitterBuffer ) ;
stm - > decoder - > SetFrameDuration ( stm - > frameDuration ) ;
stm - > decoder - > Start ( ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateAudioOutputState ( )
{
bool areAnyAudioStreamsEnabled = false ;
for ( auto s = incomingStreams . begin ( ) ; s ! = incomingStreams . end ( ) ; + + s )
{
if ( ( * s ) - > type = = STREAM_TYPE_AUDIO & & ( * s ) - > enabled )
areAnyAudioStreamsEnabled = true ;
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
if ( audioOutput )
{
2018-11-21 19:22:31 +01:00
LOGV ( " New audio output state: %d " , areAnyAudioStreamsEnabled ) ;
2020-01-22 12:43:51 +01:00
if ( audioOutput - > IsPlaying ( ) ! = areAnyAudioStreamsEnabled )
{
if ( areAnyAudioStreamsEnabled )
2018-11-18 00:36:55 +01:00
audioOutput - > Start ( ) ;
else
audioOutput - > Stop ( ) ;
}
}
}
# pragma mark - Bandwidth management
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateAudioBitrateLimit ( )
{
if ( encoder )
{
if ( dataSavingMode | | dataSavingRequestedByPeer )
{
maxBitrate = maxAudioBitrateSaving ;
2018-11-18 00:36:55 +01:00
encoder - > SetBitrate ( initAudioBitrateSaving ) ;
2020-01-22 12:43:51 +01:00
}
else if ( networkType = = NET_TYPE_GPRS )
{
maxBitrate = maxAudioBitrateGPRS ;
2018-11-18 00:36:55 +01:00
encoder - > SetBitrate ( initAudioBitrateGPRS ) ;
2020-01-22 12:43:51 +01:00
}
else if ( networkType = = NET_TYPE_EDGE )
{
maxBitrate = maxAudioBitrateEDGE ;
2018-11-18 00:36:55 +01:00
encoder - > SetBitrate ( initAudioBitrateEDGE ) ;
2020-01-22 12:43:51 +01:00
}
else
{
maxBitrate = maxAudioBitrate ;
2018-11-18 00:36:55 +01:00
encoder - > SetBitrate ( initAudioBitrate ) ;
}
2018-11-30 13:39:31 +01:00
encoder - > SetVadMode ( dataSavingMode | | dataSavingRequestedByPeer ) ;
2020-01-22 12:43:51 +01:00
if ( echoCanceller )
2018-11-30 13:39:31 +01:00
echoCanceller - > SetVoiceDetectionEnabled ( dataSavingMode | | dataSavingRequestedByPeer ) ;
2018-11-18 00:36:55 +01:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateDataSavingState ( )
{
if ( config . dataSaving = = DATA_SAVING_ALWAYS )
{
dataSavingMode = true ;
}
else if ( config . dataSaving = = DATA_SAVING_MOBILE )
{
dataSavingMode = networkType = = NET_TYPE_GPRS | | networkType = = NET_TYPE_EDGE | |
networkType = = NET_TYPE_3G | | networkType = = NET_TYPE_HSPA | | networkType = = NET_TYPE_LTE | | networkType = = NET_TYPE_OTHER_MOBILE ;
}
else
{
dataSavingMode = false ;
2018-11-18 00:36:55 +01:00
}
LOGI ( " update data saving mode, config %d, enabled %d, reqd by peer %d " , config . dataSaving , dataSavingMode , dataSavingRequestedByPeer ) ;
}
# pragma mark - Networking & crypto
2020-01-22 12:43:51 +01:00
uint32_t VoIPController : : GenerateOutSeq ( )
{
2018-11-18 00:36:55 +01:00
return seq + + ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : WritePacketHeader ( uint32_t pseq , BufferOutputStream * s , unsigned char type , uint32_t length , PacketSender * source )
{
uint32_t acks = 0 ;
uint32_t distance ;
for ( const uint32_t & seq : recentIncomingSeqs )
{
distance = lastRemoteSeq - seq ;
if ( distance > 0 & & distance < = 32 )
{
acks | = ( 1 < < ( 32 - distance ) ) ;
2019-04-15 01:43:10 +02:00
}
2018-11-18 00:36:55 +01:00
}
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 8 | | ( ! peerVersion & & connectionMaxLayer > = 92 ) )
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( type ) ;
2018-11-18 00:36:55 +01:00
s - > WriteInt32 ( lastRemoteSeq ) ;
s - > WriteInt32 ( pseq ) ;
s - > WriteInt32 ( acks ) ;
2019-03-10 23:12:09 +01:00
unsigned char flags ;
2020-01-22 12:43:51 +01:00
if ( currentExtras . empty ( ) )
{
flags = 0 ;
}
else
{
flags = XPFLAG_HAS_EXTRA ;
2019-03-10 23:12:09 +01:00
}
2020-01-22 12:43:51 +01:00
shared_ptr < Stream > videoStream = GetStreamByType ( STREAM_TYPE_VIDEO , false ) ;
if ( peerVersion > = 9 & & videoStream & & videoStream - > enabled )
2019-03-10 23:12:09 +01:00
flags | = XPFLAG_HAS_RECV_TS ;
s - > WriteByte ( flags ) ;
2020-01-22 12:43:51 +01:00
if ( ! currentExtras . empty ( ) )
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( static_cast < unsigned char > ( currentExtras . size ( ) ) ) ;
2020-01-22 12:43:51 +01:00
for ( vector < UnacknowledgedExtraData > : : iterator x = currentExtras . begin ( ) ; x ! = currentExtras . end ( ) ; + + x )
{
2019-12-05 09:06:41 +01:00
LOGV ( " Writing extra into header: type %u, length %d " , x - > type , int ( x - > data . Length ( ) ) ) ;
2020-01-22 12:43:51 +01:00
assert ( x - > data . Length ( ) < = 254 ) ;
s - > WriteByte ( static_cast < unsigned char > ( x - > data . Length ( ) + 1 ) ) ;
2018-11-23 00:46:23 +01:00
s - > WriteByte ( x - > type ) ;
s - > WriteBytes ( * x - > data , x - > data . Length ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( x - > firstContainingSeq = = 0 )
x - > firstContainingSeq = pseq ;
2018-11-18 00:36:55 +01:00
}
}
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 9 & & videoStream & & videoStream - > enabled )
{
s - > WriteInt32 ( ( uint32_t ) ( ( lastRecvPacketTime - connectionInitTime ) * 1000.0 ) ) ;
2019-03-10 23:12:09 +01:00
}
2020-01-22 12:43:51 +01:00
}
else
{
if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK )
{
2018-11-23 00:46:23 +01:00
s - > WriteInt32 ( TLID_DECRYPTED_AUDIO_BLOCK ) ;
int64_t randomID ;
2020-01-22 12:43:51 +01:00
crypto . rand_bytes ( ( uint8_t * ) & randomID , 8 ) ;
2018-11-23 00:46:23 +01:00
s - > WriteInt64 ( randomID ) ;
unsigned char randBytes [ 7 ] ;
crypto . rand_bytes ( randBytes , 7 ) ;
s - > WriteByte ( 7 ) ;
s - > WriteBytes ( randBytes , 7 ) ;
2020-01-22 12:43:51 +01:00
uint32_t pflags = PFLAG_HAS_RECENT_RECV | PFLAG_HAS_SEQ ;
if ( length > 0 )
pflags | = PFLAG_HAS_DATA ;
if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK )
{
pflags | = PFLAG_HAS_CALL_ID | PFLAG_HAS_PROTO ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
pflags | = ( ( uint32_t ) type ) < < 24 ;
2018-11-23 00:46:23 +01:00
s - > WriteInt32 ( pflags ) ;
2020-01-22 12:43:51 +01:00
if ( pflags & PFLAG_HAS_CALL_ID )
{
2018-11-23 00:46:23 +01:00
s - > WriteBytes ( callID , 16 ) ;
}
s - > WriteInt32 ( lastRemoteSeq ) ;
s - > WriteInt32 ( pseq ) ;
s - > WriteInt32 ( acks ) ;
2020-01-22 12:43:51 +01:00
if ( pflags & PFLAG_HAS_PROTO )
{
2018-11-23 00:46:23 +01:00
s - > WriteInt32 ( PROTOCOL_NAME ) ;
}
2020-01-22 12:43:51 +01:00
if ( length > 0 )
{
if ( length < = 253 )
{
s - > WriteByte ( ( unsigned char ) length ) ;
}
else
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( 254 ) ;
2020-01-22 12:43:51 +01:00
s - > WriteByte ( ( unsigned char ) ( length & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 8 ) & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 16 ) & 0xFF ) ) ;
2018-11-23 00:46:23 +01:00
}
}
2020-01-22 12:43:51 +01:00
}
else
{
2018-11-23 00:46:23 +01:00
s - > WriteInt32 ( TLID_SIMPLE_AUDIO_BLOCK ) ;
int64_t randomID ;
2020-01-22 12:43:51 +01:00
crypto . rand_bytes ( ( uint8_t * ) & randomID , 8 ) ;
2018-11-23 00:46:23 +01:00
s - > WriteInt64 ( randomID ) ;
unsigned char randBytes [ 7 ] ;
crypto . rand_bytes ( randBytes , 7 ) ;
s - > WriteByte ( 7 ) ;
s - > WriteBytes ( randBytes , 7 ) ;
2020-01-22 12:43:51 +01:00
uint32_t lenWithHeader = length + 13 ;
if ( lenWithHeader > 0 )
{
if ( lenWithHeader < = 253 )
{
s - > WriteByte ( ( unsigned char ) lenWithHeader ) ;
}
else
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( 254 ) ;
2020-01-22 12:43:51 +01:00
s - > WriteByte ( ( unsigned char ) ( lenWithHeader & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( lenWithHeader > > 8 ) & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( lenWithHeader > > 16 ) & 0xFF ) ) ;
2018-11-23 00:46:23 +01:00
}
}
s - > WriteByte ( type ) ;
s - > WriteInt32 ( lastRemoteSeq ) ;
s - > WriteInt32 ( pseq ) ;
s - > WriteInt32 ( acks ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 6 )
{
if ( currentExtras . empty ( ) )
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( 0 ) ;
2020-01-22 12:43:51 +01:00
}
else
{
2018-11-23 00:46:23 +01:00
s - > WriteByte ( XPFLAG_HAS_EXTRA ) ;
s - > WriteByte ( static_cast < unsigned char > ( currentExtras . size ( ) ) ) ;
2020-01-22 12:43:51 +01:00
for ( vector < UnacknowledgedExtraData > : : iterator x = currentExtras . begin ( ) ; x ! = currentExtras . end ( ) ; + + x )
{
2019-12-05 09:06:41 +01:00
LOGV ( " Writing extra into header: type %u, length %d " , x - > type , int ( x - > data . Length ( ) ) ) ;
2020-01-22 12:43:51 +01:00
assert ( x - > data . Length ( ) < = 254 ) ;
s - > WriteByte ( static_cast < unsigned char > ( x - > data . Length ( ) + 1 ) ) ;
2018-11-23 00:46:23 +01:00
s - > WriteByte ( x - > type ) ;
s - > WriteBytes ( * x - > data , x - > data . Length ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( x - > firstContainingSeq = = 0 )
x - > firstContainingSeq = pseq ;
2018-11-23 00:46:23 +01:00
}
2018-06-04 21:37:43 +02:00
}
}
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
unacknowledgedIncomingPacketCount = 0 ;
2018-05-15 20:23:46 +02:00
recentOutgoingPackets . push_back ( RecentOutgoingPacket {
2020-01-22 12:43:51 +01:00
pseq ,
0 ,
GetCurrentTime ( ) ,
0 ,
type ,
length ,
source ,
false } ) ;
while ( recentOutgoingPackets . size ( ) > MAX_RECENT_PACKETS )
{
2018-05-15 20:23:46 +02:00
recentOutgoingPackets . erase ( recentOutgoingPackets . begin ( ) ) ;
2019-03-10 23:12:09 +01:00
}
2020-01-22 12:43:51 +01:00
lastSentSeq = pseq ;
2017-02-02 17:24:40 +01:00
//LOGI("packet header size %d", s->GetLength());
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendInit ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
uint32_t initSeq = GenerateOutSeq ( ) ;
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
if ( e . type = = Endpoint : : Type : : TCP_RELAY & & ! useTCP )
2019-04-15 01:43:10 +02:00
continue ;
BufferOutputStream out ( 1024 ) ;
out . WriteInt32 ( PROTOCOL_VERSION ) ;
out . WriteInt32 ( MIN_PROTOCOL_VERSION ) ;
2020-01-22 12:43:51 +01:00
uint32_t flags = 0 ;
if ( config . enableCallUpgrade )
flags | = INIT_FLAG_GROUP_CALLS_SUPPORTED ;
if ( config . enableVideoReceive )
flags | = INIT_FLAG_VIDEO_RECV_SUPPORTED ;
if ( config . enableVideoSend )
flags | = INIT_FLAG_VIDEO_SEND_SUPPORTED ;
if ( dataSavingMode )
flags | = INIT_FLAG_DATA_SAVING_ENABLED ;
2019-04-15 01:43:10 +02:00
out . WriteInt32 ( flags ) ;
2020-01-22 12:43:51 +01:00
if ( connectionMaxLayer < 74 )
{
2019-04-15 01:43:10 +02:00
out . WriteByte ( 2 ) ; // audio codecs count
out . WriteByte ( CODEC_OPUS_OLD ) ;
out . WriteByte ( 0 ) ;
out . WriteByte ( 0 ) ;
out . WriteByte ( 0 ) ;
out . WriteInt32 ( CODEC_OPUS ) ;
out . WriteByte ( 0 ) ; // video codecs count (decode)
out . WriteByte ( 0 ) ; // video codecs count (encode)
2020-01-22 12:43:51 +01:00
}
else
{
2019-04-15 01:43:10 +02:00
out . WriteByte ( 1 ) ;
out . WriteInt32 ( CODEC_OPUS ) ;
2020-01-22 12:43:51 +01:00
vector < uint32_t > decoders = config . enableVideoReceive ? video : : VideoRenderer : : GetAvailableDecoders ( ) : vector < uint32_t > ( ) ;
vector < uint32_t > encoders = config . enableVideoSend ? video : : VideoSource : : GetAvailableEncoders ( ) : vector < uint32_t > ( ) ;
2019-04-15 01:43:10 +02:00
out . WriteByte ( ( unsigned char ) decoders . size ( ) ) ;
2020-01-22 12:43:51 +01:00
for ( uint32_t id : decoders )
{
2019-04-15 01:43:10 +02:00
out . WriteInt32 ( id ) ;
}
2020-01-22 12:43:51 +01:00
if ( connectionMaxLayer > = 92 )
2019-04-15 01:43:10 +02:00
out . WriteByte ( ( unsigned char ) video : : VideoRenderer : : GetMaximumResolution ( ) ) ;
else
2018-05-15 20:23:46 +02:00
out . WriteByte ( 0 ) ;
2017-07-03 03:42:49 +02:00
}
2019-04-15 01:43:10 +02:00
SendOrEnqueuePacket ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ initSeq ,
/*.type=*/ PKT_INIT ,
/*.len=*/ out . GetLength ( ) ,
/*.data=*/ Buffer ( move ( out ) ) ,
/*.endpoint=*/ e . id } ) ;
2017-03-30 16:06:59 +02:00
}
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( state = = STATE_WAIT_INIT )
2018-08-03 16:26:00 +02:00
SetState ( STATE_WAIT_INIT_ACK ) ;
2020-01-22 12:43:51 +01:00
messageThread . Post ( [ this ] {
if ( state = = STATE_WAIT_INIT_ACK )
{
2018-07-17 18:48:21 +02:00
SendInit ( ) ;
}
2020-01-22 12:43:51 +01:00
} ,
0.5 ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : InitUDPProxy ( )
{
if ( realUdpSocket ! = udpSocket )
{
2017-07-03 03:42:49 +02:00
udpSocket - > Close ( ) ;
delete udpSocket ;
2020-01-22 12:43:51 +01:00
udpSocket = realUdpSocket ;
2017-07-03 03:42:49 +02:00
}
2018-12-19 17:51:45 +01:00
char sbuf [ 128 ] ;
snprintf ( sbuf , sizeof ( sbuf ) , " %s:%u " , proxyAddress . c_str ( ) , proxyPort ) ;
string proxyHostPort ( sbuf ) ;
2020-01-22 12:43:51 +01:00
if ( proxyHostPort = = lastTestedProxyServer & & ! proxySupportsUDP )
{
2018-12-19 17:51:45 +01:00
LOGI ( " Proxy does not support UDP - using UDP directly instead " ) ;
2020-01-22 12:43:51 +01:00
messageThread . Post ( bind ( & VoIPController : : ResetUdpAvailability , this ) ) ;
2018-12-19 17:51:45 +01:00
return ;
}
2020-01-22 12:43:51 +01:00
NetworkSocket * tcp = NetworkSocket : : Create ( NetworkProtocol : : TCP ) ;
2017-07-03 03:42:49 +02:00
tcp - > Connect ( resolvedProxyAddress , proxyPort ) ;
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
vector < NetworkSocket * > writeSockets ;
vector < NetworkSocket * > readSockets ;
vector < NetworkSocket * > errorSockets ;
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
while ( ! tcp - > IsFailed ( ) & & ! tcp - > IsReadyToSend ( ) )
{
2018-11-09 16:44:01 +01:00
writeSockets . push_back ( tcp ) ;
2020-01-22 12:43:51 +01:00
if ( ! NetworkSocket : : Select ( readSockets , writeSockets , errorSockets , selectCanceller ) )
{
2018-11-09 16:44:01 +01:00
LOGW ( " Select canceled while waiting for proxy control socket to connect " ) ;
delete tcp ;
return ;
}
2017-07-03 03:42:49 +02:00
}
2018-11-09 16:44:01 +01:00
LOGV ( " UDP proxy control socket ready to send " ) ;
2020-01-22 12:43:51 +01:00
NetworkSocketSOCKS5Proxy * udpProxy = new NetworkSocketSOCKS5Proxy ( tcp , realUdpSocket , proxyUsername , proxyPassword ) ;
2018-11-09 16:44:01 +01:00
udpProxy - > OnReadyToSend ( ) ;
writeSockets . clear ( ) ;
2020-01-22 12:43:51 +01:00
while ( ! udpProxy - > IsFailed ( ) & & ! tcp - > IsFailed ( ) & & ! udpProxy - > IsReadyToSend ( ) )
{
2018-11-09 16:44:01 +01:00
readSockets . clear ( ) ;
errorSockets . clear ( ) ;
readSockets . push_back ( tcp ) ;
errorSockets . push_back ( tcp ) ;
2020-01-22 12:43:51 +01:00
if ( ! NetworkSocket : : Select ( readSockets , writeSockets , errorSockets , selectCanceller ) )
{
2018-11-09 16:44:01 +01:00
LOGW ( " Select canceled while waiting for UDP proxy to initialize " ) ;
delete udpProxy ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( ! readSockets . empty ( ) )
2018-11-09 16:44:01 +01:00
udpProxy - > OnReadyToReceive ( ) ;
}
LOGV ( " UDP proxy initialized " ) ;
2020-01-22 12:43:51 +01:00
if ( udpProxy - > IsFailed ( ) )
{
2017-07-03 03:42:49 +02:00
udpProxy - > Close ( ) ;
delete udpProxy ;
2020-01-22 12:43:51 +01:00
proxySupportsUDP = false ;
}
else
{
udpSocket = udpProxy ;
2017-07-03 03:42:49 +02:00
}
2019-04-15 01:43:10 +02:00
messageThread . Post ( bind ( & VoIPController : : ResetUdpAvailability , this ) ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : RunRecvThread ( )
{
2017-02-02 17:24:40 +01:00
LOGI ( " Receive thread starting " ) ;
2020-01-22 12:43:51 +01:00
if ( proxyProtocol = = PROXY_SOCKS5 )
{
resolvedProxyAddress = NetworkSocket : : ResolveDomainName ( proxyAddress ) ;
if ( resolvedProxyAddress . IsEmpty ( ) )
{
2018-11-09 16:44:01 +01:00
LOGW ( " Error resolving proxy address %s " , proxyAddress . c_str ( ) ) ;
SetState ( STATE_FAILED ) ;
return ;
}
}
2020-01-22 12:43:51 +01:00
else
{
udpConnectivityState = UDP_PING_PENDING ;
udpPingTimeoutID = messageThread . Post ( std : : bind ( & VoIPController : : SendUdpPings , this ) , 0.0 , 0.5 ) ;
}
while ( runReceiver )
{
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
if ( proxyProtocol = = PROXY_SOCKS5 & & needReInitUdpProxy )
{
2018-11-09 16:44:01 +01:00
InitUDPProxy ( ) ;
2020-01-22 12:43:51 +01:00
needReInitUdpProxy = false ;
2018-11-09 16:44:01 +01:00
}
2019-12-05 09:06:41 +01:00
2020-01-22 12:43:51 +01:00
vector < NetworkSocket * > readSockets ;
vector < NetworkSocket * > errorSockets ;
vector < NetworkSocket * > writeSockets ;
2018-08-27 13:39:27 +02:00
readSockets . push_back ( udpSocket ) ;
2017-07-03 03:42:49 +02:00
errorSockets . push_back ( realUdpSocket ) ;
2020-01-22 12:43:51 +01:00
if ( ! realUdpSocket - > IsReadyToSend ( ) )
2018-11-09 16:44:01 +01:00
writeSockets . push_back ( realUdpSocket ) ;
2019-12-05 09:06:41 +01:00
2018-06-04 21:37:43 +02:00
{
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
const Endpoint & e = _e . second ;
if ( e . type = = Endpoint : : Type : : TCP_RELAY )
{
if ( e . socket )
{
2019-04-15 01:43:10 +02:00
readSockets . push_back ( & * e . socket ) ;
errorSockets . push_back ( & * e . socket ) ;
2020-01-22 12:43:51 +01:00
if ( ! e . socket - > IsReadyToSend ( ) )
{
NetworkSocketSOCKS5Proxy * proxy = dynamic_cast < NetworkSocketSOCKS5Proxy * > ( & * e . socket ) ;
if ( ! proxy | | proxy - > NeedSelectForSending ( ) )
writeSockets . push_back ( & * e . socket ) ;
2018-11-09 16:44:01 +01:00
}
2017-07-03 03:42:49 +02:00
}
}
}
2018-06-04 21:37:43 +02:00
}
2017-07-03 03:42:49 +02:00
2018-06-04 21:37:43 +02:00
{
2020-01-22 12:43:51 +01:00
bool selRes = NetworkSocket : : Select ( readSockets , writeSockets , errorSockets , selectCanceller ) ;
if ( ! selRes )
{
2018-06-04 21:37:43 +02:00
LOGV ( " Select canceled " ) ;
continue ;
}
2017-07-03 03:42:49 +02:00
}
2020-01-22 12:43:51 +01:00
if ( ! runReceiver )
2017-07-03 03:42:49 +02:00
return ;
2020-01-22 12:43:51 +01:00
if ( ! errorSockets . empty ( ) )
{
if ( find ( errorSockets . begin ( ) , errorSockets . end ( ) , realUdpSocket ) ! = errorSockets . end ( ) )
{
2017-07-03 03:42:49 +02:00
LOGW ( " UDP socket failed " ) ;
SetState ( STATE_FAILED ) ;
return ;
}
2018-05-15 20:23:46 +02:00
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
for ( NetworkSocket * & socket : errorSockets )
{
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
if ( e . socket & & & * e . socket = = socket )
{
2018-11-09 16:44:01 +01:00
e . socket - > Close ( ) ;
2019-04-15 01:43:10 +02:00
e . socket . reset ( ) ;
2018-11-09 16:44:01 +01:00
LOGI ( " Closing failed TCP socket for %s:%u " , e . GetAddress ( ) . ToString ( ) . c_str ( ) , e . port ) ;
2017-07-03 03:42:49 +02:00
}
}
}
continue ;
}
2020-01-22 12:43:51 +01:00
for ( NetworkSocket * & socket : readSockets )
{
2018-11-09 16:44:01 +01:00
//while(packet.length){
2020-01-22 12:43:51 +01:00
NetworkPacket packet = socket - > Receive ( ) ;
if ( packet . address . IsEmpty ( ) )
{
2018-08-03 16:26:00 +02:00
LOGE ( " Packet has null address. This shouldn't happen. " ) ;
continue ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
if ( packet . data . IsEmpty ( ) )
{
2018-08-03 16:26:00 +02:00
LOGE ( " Packet has zero length. " ) ;
continue ;
}
//LOGV("Received %d bytes from %s:%d at %.5lf", len, packet.address->ToString().c_str(), packet.port, GetCurrentTime());
2019-04-15 01:43:10 +02:00
messageThread . Post ( bind ( & VoIPController : : NetworkPacketReceived , this , make_shared < NetworkPacket > ( move ( packet ) ) ) ) ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
if ( ! writeSockets . empty ( ) )
{
2019-04-15 01:43:10 +02:00
messageThread . Post ( bind ( & VoIPController : : TrySendQueuedPackets , this ) ) ;
2018-05-15 20:23:46 +02:00
}
}
LOGI ( " === recv thread exiting === " ) ;
}
2017-05-09 22:26:18 +02:00
2020-01-22 12:43:51 +01:00
void VoIPController : : TrySendQueuedPackets ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
for ( vector < PendingOutgoingPacket > : : iterator opkt = sendQueue . begin ( ) ; opkt ! = sendQueue . end ( ) ; )
{
Endpoint * endpoint = GetEndpointForPacket ( * opkt ) ;
if ( ! endpoint )
{
opkt = sendQueue . erase ( opkt ) ;
2019-04-15 01:43:10 +02:00
LOGE ( " SendQueue contained packet for nonexistent endpoint " ) ;
continue ;
}
bool canSend ;
2020-01-22 12:43:51 +01:00
if ( endpoint - > type ! = Endpoint : : Type : : TCP_RELAY )
canSend = realUdpSocket - > IsReadyToSend ( ) ;
2019-04-15 01:43:10 +02:00
else
2020-01-22 12:43:51 +01:00
canSend = endpoint - > socket & & endpoint - > socket - > IsReadyToSend ( ) ;
if ( canSend )
{
2019-04-15 01:43:10 +02:00
LOGI ( " Sending queued packet " ) ;
SendOrEnqueuePacket ( move ( * opkt ) , false ) ;
2020-01-22 12:43:51 +01:00
opkt = sendQueue . erase ( opkt ) ;
}
else
{
2019-04-15 01:43:10 +02:00
+ + opkt ;
}
}
}
2020-01-22 12:43:51 +01:00
bool VoIPController : : WasOutgoingPacketAcknowledged ( uint32_t seq )
{
RecentOutgoingPacket * pkt = GetRecentOutgoingPacket ( seq ) ;
if ( ! pkt )
2019-03-10 23:12:09 +01:00
return false ;
2020-01-22 12:43:51 +01:00
return pkt - > ackTime ! = 0.0 ;
2019-03-10 23:12:09 +01:00
}
2020-01-22 12:43:51 +01:00
VoIPController : : RecentOutgoingPacket * VoIPController : : GetRecentOutgoingPacket ( uint32_t seq )
{
for ( RecentOutgoingPacket & opkt : recentOutgoingPackets )
{
if ( opkt . seq = = seq )
{
2019-03-10 23:12:09 +01:00
return & opkt ;
2019-02-05 12:41:00 +01:00
}
}
2019-03-10 23:12:09 +01:00
return NULL ;
2019-02-05 12:41:00 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : NetworkPacketReceived ( shared_ptr < NetworkPacket > _packet )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
NetworkPacket & packet = * _packet ;
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
int64_t srcEndpointID = 0 ;
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( ! packet . address . isIPv6 )
{
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
const Endpoint & e = _e . second ;
if ( e . address = = packet . address & & e . port = = packet . port )
{
if ( ( e . type ! = Endpoint : : Type : : TCP_RELAY & & packet . protocol = = NetworkProtocol : : UDP ) | | ( e . type = = Endpoint : : Type : : TCP_RELAY & & packet . protocol = = NetworkProtocol : : TCP ) )
{
srcEndpointID = e . id ;
2019-04-15 01:43:10 +02:00
break ;
}
}
}
2020-01-22 12:43:51 +01:00
if ( ! srcEndpointID & & packet . protocol = = NetworkProtocol : : UDP )
{
try
{
Endpoint & p2p = GetEndpointByType ( Endpoint : : Type : : UDP_P2P_INET ) ;
if ( p2p . rtts [ 0 ] = = 0.0 & & p2p . address . PrefixMatches ( 24 , packet . address ) )
{
2019-04-15 01:43:10 +02:00
LOGD ( " Packet source matches p2p endpoint partially: %s:%u " , packet . address . ToString ( ) . c_str ( ) , packet . port ) ;
2020-01-22 12:43:51 +01:00
srcEndpointID = p2p . id ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
}
catch ( out_of_range & ex )
{
}
}
}
else
{
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
const Endpoint & e = _e . second ;
if ( e . v6address = = packet . address & & e . port = = packet . port & & e . IsIPv6Only ( ) )
{
if ( ( e . type ! = Endpoint : : Type : : TCP_RELAY & & packet . protocol = = NetworkProtocol : : UDP ) | | ( e . type = = Endpoint : : Type : : TCP_RELAY & & packet . protocol = = NetworkProtocol : : TCP ) )
{
srcEndpointID = e . id ;
2019-04-15 01:43:10 +02:00
break ;
}
}
}
}
2020-01-22 12:43:51 +01:00
if ( ! srcEndpointID )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Received a packet from unknown source %s:%u " , packet . address . ToString ( ) . c_str ( ) , packet . port ) ;
return ;
}
/*if(len<=0){
//LOGW("error receiving: %d / %s", errno, strerror(errno));
continue ;
} */
2020-01-22 12:43:51 +01:00
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesRecvdMobile + = ( uint64_t ) packet . data . Length ( ) ;
2019-04-15 01:43:10 +02:00
else
2020-01-22 12:43:51 +01:00
stats . bytesRecvdWifi + = ( uint64_t ) packet . data . Length ( ) ;
try
{
2019-04-15 01:43:10 +02:00
ProcessIncomingPacket ( packet , endpoints . at ( srcEndpointID ) ) ;
2020-01-22 12:43:51 +01:00
}
catch ( out_of_range & x )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Error parsing packet: %s " , x . what ( ) ) ;
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ProcessIncomingPacket ( NetworkPacket & packet , Endpoint & srcEndpoint )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
// Initial packet decryption and recognition
unsigned char * buffer = * packet . data ;
size_t len = packet . data . Length ( ) ;
2019-04-15 01:43:10 +02:00
BufferInputStream in ( packet . data ) ;
2020-01-22 12:43:51 +01:00
bool hasPeerTag = false ;
if ( peerVersion < 9 | | srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY | | srcEndpoint . type = = Endpoint : : Type : : TCP_RELAY )
{
if ( memcmp ( buffer , srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY | | srcEndpoint . type = = Endpoint : : Type : : TCP_RELAY ? ( void * ) srcEndpoint . peerTag : ( void * ) callID , 16 ) ! = 0 )
{
2019-02-10 13:28:22 +01:00
LOGW ( " Received packet has wrong peerTag " ) ;
return ;
}
in . Seek ( 16 ) ;
2020-01-22 12:43:51 +01:00
hasPeerTag = true ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( in . Remaining ( ) > = 16 & & ( srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY | | srcEndpoint . type = = Endpoint : : Type : : TCP_RELAY ) & & * reinterpret_cast < uint64_t * > ( buffer + 16 ) = = 0xFFFFFFFFFFFFFFFFLL & & * reinterpret_cast < uint32_t * > ( buffer + 24 ) = = 0xFFFFFFFF )
{
2018-05-15 20:23:46 +02:00
// relay special request response
2020-01-22 12:43:51 +01:00
in . Seek ( 16 + 12 ) ;
uint32_t tlid = ( uint32_t ) in . ReadInt32 ( ) ;
2018-05-15 20:23:46 +02:00
2020-01-22 12:43:51 +01:00
if ( tlid = = TLID_UDP_REFLECTOR_SELF_INFO )
{
if ( srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY /*&& udpConnectivityState==UDP_PING_SENT*/ & & in . Remaining ( ) > = 32 )
{
int32_t date = in . ReadInt32 ( ) ;
int64_t queryID = in . ReadInt64 ( ) ;
2018-05-15 20:23:46 +02:00
unsigned char myIP [ 16 ] ;
in . ReadBytes ( myIP , 16 ) ;
2020-01-22 12:43:51 +01:00
int32_t myPort = in . ReadInt32 ( ) ;
2018-05-15 20:23:46 +02:00
//udpConnectivityState=UDP_AVAILABLE;
2020-01-22 12:43:51 +01:00
double selfRTT = 0.0 ;
2018-11-09 16:44:01 +01:00
srcEndpoint . udpPongCount + + ;
2019-04-15 01:43:10 +02:00
srcEndpoint . totalUdpPingReplies + + ;
2020-01-22 12:43:51 +01:00
if ( srcEndpoint . udpPingTimes . find ( queryID ) ! = srcEndpoint . udpPingTimes . end ( ) )
{
double sendTime = srcEndpoint . udpPingTimes [ queryID ] ;
2019-04-15 01:43:10 +02:00
srcEndpoint . udpPingTimes . erase ( queryID ) ;
2020-01-22 12:43:51 +01:00
srcEndpoint . selfRtts . Add ( selfRTT = GetCurrentTime ( ) - sendTime ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
LOGV ( " Received UDP ping reply from %s:%d: date=%d, queryID=%ld, my IP=%s, my port=%d, selfRTT=%f " , srcEndpoint . address . ToString ( ) . c_str ( ) , srcEndpoint . port , date , ( long int ) queryID , NetworkAddress : : IPv4 ( * reinterpret_cast < uint32_t * > ( myIP + 12 ) ) . ToString ( ) . c_str ( ) , myPort , selfRTT ) ;
if ( srcEndpoint . IsIPv6Only ( ) & & ! didSendIPv6Endpoint )
{
NetworkAddress realAddr = NetworkAddress : : IPv6 ( myIP ) ;
if ( realAddr = = myIPv6 )
{
2018-06-04 21:37:43 +02:00
LOGI ( " Public IPv6 matches local address " ) ;
2020-01-22 12:43:51 +01:00
useIPv6 = true ;
if ( allowP2p )
{
didSendIPv6Endpoint = true ;
2018-06-04 21:37:43 +02:00
BufferOutputStream o ( 18 ) ;
o . WriteBytes ( myIP , 16 ) ;
o . WriteInt16 ( udpSocket - > GetLocalPort ( ) ) ;
Buffer b ( move ( o ) ) ;
SendExtra ( b , EXTRA_TYPE_IPV6_ENDPOINT ) ;
}
}
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
}
else if ( tlid = = TLID_UDP_REFLECTOR_PEER_INFO )
{
if ( in . Remaining ( ) > = 16 )
{
uint32_t myAddr = ( uint32_t ) in . ReadInt32 ( ) ;
uint32_t myPort = ( uint32_t ) in . ReadInt32 ( ) ;
uint32_t peerAddr = ( uint32_t ) in . ReadInt32 ( ) ;
uint32_t peerPort = ( uint32_t ) in . ReadInt32 ( ) ;
2018-11-09 16:44:01 +01:00
2020-01-22 12:43:51 +01:00
constexpr int64_t p2pID = ( int64_t ) ( FOURCC ( ' P ' , ' 2 ' , ' P ' , ' 4 ' ) ) < < 32 ;
constexpr int64_t lanID = ( int64_t ) ( FOURCC ( ' L ' , ' A ' , ' N ' , ' 4 ' ) ) < < 32 ;
2018-11-09 16:44:01 +01:00
2020-01-22 12:43:51 +01:00
if ( currentEndpoint = = p2pID | | currentEndpoint = = lanID )
currentEndpoint = preferredRelay ;
2018-11-09 16:44:01 +01:00
2020-01-22 12:43:51 +01:00
if ( endpoints . find ( lanID ) ! = endpoints . end ( ) )
{
2019-04-15 01:43:10 +02:00
MutexGuard m ( endpointsMutex ) ;
endpoints . erase ( lanID ) ;
}
2018-11-09 16:44:01 +01:00
2018-05-15 20:23:46 +02:00
unsigned char peerTag [ 16 ] ;
2019-04-15 01:43:10 +02:00
LOGW ( " Received reflector peer info, my=%s:%u, peer=%s:%u " , NetworkAddress : : IPv4 ( myAddr ) . ToString ( ) . c_str ( ) , myPort , NetworkAddress : : IPv4 ( peerAddr ) . ToString ( ) . c_str ( ) , peerPort ) ;
2020-01-22 12:43:51 +01:00
if ( waitingForRelayPeerInfo )
{
Endpoint p2p ( p2pID , ( uint16_t ) peerPort , NetworkAddress : : IPv4 ( peerAddr ) , NetworkAddress : : Empty ( ) , Endpoint : : Type : : UDP_P2P_INET , peerTag ) ;
2019-04-15 01:43:10 +02:00
{
2020-01-22 12:43:51 +01:00
MutexGuard m ( endpointsMutex ) ;
endpoints [ p2pID ] = p2p ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( myAddr = = peerAddr )
{
2019-02-10 13:28:22 +01:00
LOGW ( " Detected LAN " ) ;
2020-01-22 12:43:51 +01:00
NetworkAddress lanAddr = NetworkAddress : : IPv4 ( 0 ) ;
2019-02-10 13:28:22 +01:00
udpSocket - > GetLocalInterfaceInfo ( & lanAddr , NULL ) ;
BufferOutputStream pkt ( 8 ) ;
2019-04-15 01:43:10 +02:00
pkt . WriteInt32 ( lanAddr . addr . ipv4 ) ;
2019-02-10 13:28:22 +01:00
pkt . WriteInt32 ( udpSocket - > GetLocalPort ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion < 6 )
{
2019-02-10 13:28:22 +01:00
SendPacketReliably ( PKT_LAN_ENDPOINT , pkt . GetBuffer ( ) , pkt . GetLength ( ) , 0.5 , 10 ) ;
2020-01-22 12:43:51 +01:00
}
else
{
2019-02-10 13:28:22 +01:00
Buffer buf ( move ( pkt ) ) ;
SendExtra ( buf , EXTRA_TYPE_LAN_ENDPOINT ) ;
}
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
waitingForRelayPeerInfo = false ;
2018-05-15 20:23:46 +02:00
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
}
else
{
2018-05-15 20:23:46 +02:00
LOGV ( " Received relay response with unknown tl id: 0x%08X " , tlid ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
return ;
}
2020-01-22 12:43:51 +01:00
if ( in . Remaining ( ) < 40 )
{
2018-05-15 20:23:46 +02:00
LOGV ( " Received packet is too small " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
bool retryWith2 = false ;
size_t innerLen = 0 ;
bool shortFormat = peerVersion > = 8 | | ( ! peerVersion & & connectionMaxLayer > = 92 ) ;
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
if ( ! useMTProto2 )
{
2017-02-02 17:24:40 +01:00
unsigned char fingerprint [ 8 ] , msgHash [ 16 ] ;
2017-04-28 13:17:56 +02:00
in . ReadBytes ( fingerprint , 8 ) ;
in . ReadBytes ( msgHash , 16 ) ;
2017-02-02 17:24:40 +01:00
unsigned char key [ 32 ] , iv [ 32 ] ;
2017-03-30 16:06:59 +02:00
KDF ( msgHash , isOutgoing ? 8 : 0 , key , iv ) ;
2018-05-15 20:23:46 +02:00
unsigned char aesOut [ MSC_STACK_FALLBACK ( in . Remaining ( ) , 1500 ) ] ;
2020-01-22 12:43:51 +01:00
if ( in . Remaining ( ) > sizeof ( aesOut ) )
2018-05-15 20:23:46 +02:00
return ;
2020-01-22 12:43:51 +01:00
crypto . aes_ige_decrypt ( ( unsigned char * ) buffer + in . GetOffset ( ) , aesOut , in . Remaining ( ) , key , iv ) ;
2018-05-15 20:23:46 +02:00
BufferInputStream _in ( aesOut , in . Remaining ( ) ) ;
2017-02-02 17:24:40 +01:00
unsigned char sha [ SHA1_LENGTH ] ;
2020-01-22 12:43:51 +01:00
uint32_t _len = ( uint32_t ) _in . ReadInt32 ( ) ;
if ( _len > _in . Remaining ( ) )
_len = ( uint32_t ) _in . Remaining ( ) ;
crypto . sha1 ( ( uint8_t * ) ( aesOut ) , ( size_t ) ( _len + 4 ) , sha ) ;
if ( memcmp ( msgHash , sha + ( SHA1_LENGTH - 16 ) , 16 ) ! = 0 )
{
2017-02-02 17:24:40 +01:00
LOGW ( " Received packet has wrong hash after decryption " ) ;
2020-01-22 12:43:51 +01:00
if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK )
retryWith2 = true ;
2018-05-15 20:23:46 +02:00
else
return ;
2020-01-22 12:43:51 +01:00
}
else
{
memcpy ( buffer + in . GetOffset ( ) , aesOut , in . Remaining ( ) ) ;
2018-05-15 20:23:46 +02:00
in . ReadInt32 ( ) ;
}
}
2017-05-09 22:26:18 +02:00
2020-01-22 12:43:51 +01:00
if ( useMTProto2 | | retryWith2 )
{
if ( hasPeerTag )
2019-02-10 13:28:22 +01:00
in . Seek ( 16 ) ; // peer tag
2018-05-15 20:23:46 +02:00
unsigned char fingerprint [ 8 ] , msgKey [ 16 ] ;
2020-01-22 12:43:51 +01:00
if ( ! shortFormat )
{
2018-11-23 00:46:23 +01:00
in . ReadBytes ( fingerprint , 8 ) ;
2020-01-22 12:43:51 +01:00
if ( memcmp ( fingerprint , keyFingerprint , 8 ) ! = 0 )
{
2018-11-23 00:46:23 +01:00
LOGW ( " Received packet has wrong key fingerprint " ) ;
return ;
}
2018-05-15 20:23:46 +02:00
}
in . ReadBytes ( msgKey , 16 ) ;
unsigned char decrypted [ 1500 ] ;
unsigned char aesKey [ 32 ] , aesIv [ 32 ] ;
KDF2 ( msgKey , isOutgoing ? 8 : 0 , aesKey , aesIv ) ;
2020-01-22 12:43:51 +01:00
size_t decryptedLen = in . Remaining ( ) ;
if ( decryptedLen > sizeof ( decrypted ) )
2018-05-15 20:23:46 +02:00
return ;
2020-01-22 12:43:51 +01:00
if ( decryptedLen % 16 ! = 0 )
{
2018-11-09 16:44:01 +01:00
LOGW ( " wrong decrypted length " ) ;
return ;
}
2018-05-15 20:23:46 +02:00
2020-01-22 12:43:51 +01:00
crypto . aes_ige_decrypt ( * packet . data + in . GetOffset ( ) , decrypted , decryptedLen , aesKey , aesIv ) ;
2018-05-15 20:23:46 +02:00
2020-01-22 12:43:51 +01:00
in = BufferInputStream ( decrypted , decryptedLen ) ;
2018-05-15 20:23:46 +02:00
//LOGD("received packet length: %d", in.ReadInt32());
2020-01-22 12:43:51 +01:00
size_t sizeSize = shortFormat ? 0 : 4 ;
2018-05-15 20:23:46 +02:00
2020-01-22 12:43:51 +01:00
BufferOutputStream buf ( decryptedLen + 32 ) ;
size_t x = isOutgoing ? 8 : 0 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( decrypted + sizeSize , decryptedLen - sizeSize ) ;
2018-05-15 20:23:46 +02:00
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
2020-01-22 12:43:51 +01:00
if ( memcmp ( msgKey , msgKeyLarge + 8 , 16 ) ! = 0 )
{
2018-05-15 20:23:46 +02:00
LOGW ( " Received packet has wrong hash " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
innerLen = ( uint32_t ) ( shortFormat ? in . ReadInt16 ( ) : in . ReadInt32 ( ) ) ;
if ( innerLen > decryptedLen - sizeSize )
{
LOGW ( " Received packet has wrong inner length (%d with total of %u) " , ( int ) innerLen , ( unsigned int ) decryptedLen ) ;
2018-05-15 20:23:46 +02:00
return ;
}
2020-01-22 12:43:51 +01:00
if ( decryptedLen - innerLen < ( shortFormat ? 16 : 12 ) )
{
LOGW ( " Received packet has too little padding (%u) " , ( unsigned int ) ( decryptedLen - innerLen ) ) ;
2018-05-15 20:23:46 +02:00
return ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
memcpy ( buffer , decrypted + ( shortFormat ? 2 : 4 ) , innerLen ) ;
in = BufferInputStream ( buffer , ( size_t ) innerLen ) ;
if ( retryWith2 )
{
2018-05-15 20:23:46 +02:00
LOGD ( " Successfully decrypted packet in MTProto2.0 fallback, upgrading " ) ;
2020-01-22 12:43:51 +01:00
useMTProto2 = true ;
2018-05-15 20:23:46 +02:00
}
}
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
lastRecvPacketTime = GetCurrentTime ( ) ;
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
if ( state = = STATE_RECONNECTING )
{
2018-08-24 01:29:07 +02:00
LOGI ( " Received a valid packet while reconnecting - setting state to established " ) ;
SetState ( STATE_ESTABLISHED ) ;
}
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
if ( srcEndpoint . type = = Endpoint : : Type : : UDP_P2P_INET & & ! srcEndpoint . IsIPv6Only ( ) )
{
if ( srcEndpoint . port ! = packet . port | | srcEndpoint . address ! = packet . address )
{
if ( ! packet . address . isIPv6 )
{
2019-04-15 01:43:10 +02:00
LOGI ( " Incoming packet was decrypted successfully, changing P2P endpoint to %s:%u " , packet . address . ToString ( ) . c_str ( ) , packet . port ) ;
2020-01-22 12:43:51 +01:00
srcEndpoint . address = packet . address ;
srcEndpoint . port = packet . port ;
}
}
}
// decryptedAudioBlock random_id:long random_bytes:string flags:# voice_call_id:flags.2?int128 in_seq_no:flags.4?int out_seq_no:flags.4?int
// recent_received_mask:flags.5?int proto:flags.3?int extra:flags.1?string raw_data:flags.0?string = DecryptedAudioBlock
//
// simpleAudioBlock random_id:long random_bytes:string raw_data:string = DecryptedAudioBlock;
// Version-specific extraction of 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 ( shortFormat )
{
type = in . ReadByte ( ) ;
ackId = ( uint32_t ) in . ReadInt32 ( ) ;
pseq = ( uint32_t ) in . ReadInt32 ( ) ;
acks = ( uint32_t ) in . ReadInt32 ( ) ;
pflags = in . ReadByte ( ) ;
packetInnerLen = innerLen - 14 ;
}
else
{
uint32_t tlid = ( uint32_t ) in . ReadInt32 ( ) ;
if ( tlid = = TLID_DECRYPTED_AUDIO_BLOCK )
{
2018-11-23 00:46:23 +01:00
in . ReadInt64 ( ) ; // random id
2020-01-22 12:43:51 +01:00
uint32_t randLen = ( uint32_t ) in . ReadTlLength ( ) ;
in . Seek ( in . GetOffset ( ) + randLen + pad4 ( randLen ) ) ;
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
type = ( unsigned char ) ( ( flags > > 24 ) & 0xFF ) ;
if ( ! ( flags & PFLAG_HAS_SEQ & & flags & PFLAG_HAS_RECENT_RECV ) )
{
2018-11-23 00:46:23 +01:00
LOGW ( " Received packet doesn't have PFLAG_HAS_SEQ, PFLAG_HAS_RECENT_RECV, or both " ) ;
2018-05-15 20:23:46 +02:00
return ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
if ( flags & PFLAG_HAS_CALL_ID )
{
2018-11-23 00:46:23 +01:00
unsigned char pktCallID [ 16 ] ;
in . ReadBytes ( pktCallID , 16 ) ;
2020-01-22 12:43:51 +01:00
if ( memcmp ( pktCallID , callID , 16 ) ! = 0 )
{
2018-11-23 00:46:23 +01:00
LOGW ( " Received packet has wrong call id " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_UNKNOWN ;
2018-11-23 00:46:23 +01:00
SetState ( STATE_FAILED ) ;
return ;
}
}
2020-01-22 12:43:51 +01:00
ackId = ( uint32_t ) in . ReadInt32 ( ) ;
pseq = ( uint32_t ) in . ReadInt32 ( ) ;
acks = ( uint32_t ) in . ReadInt32 ( ) ;
if ( flags & PFLAG_HAS_PROTO )
{
uint32_t proto = ( uint32_t ) in . ReadInt32 ( ) ;
if ( proto ! = PROTOCOL_NAME )
{
2018-11-23 00:46:23 +01:00
LOGW ( " Received packet uses wrong protocol " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_INCOMPATIBLE ;
2018-11-23 00:46:23 +01:00
SetState ( STATE_FAILED ) ;
return ;
}
}
2020-01-22 12:43:51 +01:00
if ( flags & PFLAG_HAS_EXTRA )
{
uint32_t extraLen = ( uint32_t ) in . ReadTlLength ( ) ;
in . Seek ( in . GetOffset ( ) + extraLen + pad4 ( extraLen ) ) ;
2018-11-23 00:46:23 +01:00
}
2020-01-22 12:43:51 +01:00
if ( flags & PFLAG_HAS_DATA )
{
packetInnerLen = in . ReadTlLength ( ) ;
2018-11-23 00:46:23 +01:00
}
2020-01-22 12:43:51 +01:00
pflags = 0 ;
}
else if ( tlid = = TLID_SIMPLE_AUDIO_BLOCK )
{
2018-11-23 00:46:23 +01:00
in . ReadInt64 ( ) ; // random id
2020-01-22 12:43:51 +01:00
uint32_t randLen = ( uint32_t ) in . ReadTlLength ( ) ;
in . Seek ( in . GetOffset ( ) + randLen + pad4 ( randLen ) ) ;
packetInnerLen = in . ReadTlLength ( ) ;
type = in . ReadByte ( ) ;
ackId = ( uint32_t ) in . ReadInt32 ( ) ;
pseq = ( uint32_t ) in . ReadInt32 ( ) ;
acks = ( uint32_t ) in . ReadInt32 ( ) ;
if ( peerVersion > = 6 )
pflags = in . ReadByte ( ) ;
2018-11-23 00:46:23 +01:00
else
2020-01-22 12:43:51 +01:00
pflags = 0 ;
}
else
{
2018-11-23 00:46:23 +01:00
LOGW ( " Received a packet of unknown type %08X " , tlid ) ;
2018-05-15 20:23:46 +02:00
2018-11-23 00:46:23 +01:00
return ;
}
2018-05-15 20:23:46 +02:00
}
2018-06-04 21:37:43 +02:00
packetsReceived + + ;
2017-05-09 22:26:18 +02:00
2020-01-22 12:43:51 +01:00
// Duplicate and moving window check
if ( seqgt ( pseq , lastRemoteSeq - MAX_RECENT_PACKETS ) )
{
if ( find ( recentIncomingSeqs . begin ( ) , recentIncomingSeqs . end ( ) , pseq ) ! = recentIncomingSeqs . end ( ) )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Received duplicated packet for seq %u " , pseq ) ;
2018-05-15 20:23:46 +02:00
return ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
recentIncomingSeqs [ recentIncomingSeqIdx + + ] = pseq ;
recentIncomingSeqIdx % = recentIncomingSeqs . size ( ) ;
if ( seqgt ( pseq , lastRemoteSeq ) )
lastRemoteSeq = pseq ;
}
else
{
2018-05-15 20:23:46 +02:00
LOGW ( " Packet %u is out of order and too late " , pseq ) ;
return ;
}
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
// Extra data
if ( pflags & XPFLAG_HAS_EXTRA )
{
unsigned char extraCount = in . ReadByte ( ) ;
for ( int i = 0 ; i < extraCount ; i + + )
{
size_t extraLen = in . ReadByte ( ) ;
2019-04-15 01:43:10 +02:00
Buffer xbuffer ( extraLen ) ;
in . ReadBytes ( * xbuffer , extraLen ) ;
ProcessExtraData ( xbuffer ) ;
}
}
2020-01-22 12:43:51 +01:00
uint32_t recvTS = 0 ;
if ( pflags & XPFLAG_HAS_RECV_TS )
{
recvTS = static_cast < uint32_t > ( in . ReadInt32 ( ) ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( seqgt ( ackId , lastRemoteAckSeq ) )
{
2019-03-10 23:12:09 +01:00
2020-01-22 12:43:51 +01:00
if ( waitingForAcks & & lastRemoteAckSeq > = firstSentPing )
{
2018-07-17 18:48:21 +02:00
rttHistory . Reset ( ) ;
2020-01-22 12:43:51 +01:00
waitingForAcks = false ;
dontSendPackets = 10 ;
messageThread . Post (
[ this ] {
dontSendPackets = 0 ;
} ,
1.0 ) ;
2018-05-15 20:23:46 +02:00
LOGI ( " resuming sending " ) ;
}
2020-01-22 12:43:51 +01:00
lastRemoteAckSeq = ackId ;
2018-05-15 20:23:46 +02:00
conctl - > PacketAcknowledged ( ackId ) ;
2020-01-22 12:43:51 +01:00
// Status list of acked seqnos, starting from the seq explicitly present in the packet + up to 32 seqs ago
std : : array < uint32_t , 33 > peerAcks { 0 } ;
peerAcks [ 0 ] = ackId ;
for ( unsigned int i = 1 ; i < = 32 ; i + + )
{
if ( ( acks > > ( 32 - i ) ) & 1 )
{
peerAcks [ i ] = ackId - i ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
for ( RecentOutgoingPacket & opkt : recentOutgoingPackets )
{
if ( opkt . ackTime ! = 0.0 )
2018-05-15 20:23:46 +02:00
continue ;
2020-01-22 12:43:51 +01:00
if ( find ( peerAcks . begin ( ) , peerAcks . end ( ) , opkt . seq ) ! = peerAcks . end ( ) )
{
opkt . ackTime = GetCurrentTime ( ) ;
if ( opkt . lost )
{
2019-04-15 01:43:10 +02:00
LOGW ( " acknowledged lost packet %u " , opkt . seq ) ;
sendLosses - - ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
if ( opkt . sender & & ! opkt . lost )
{ // don't report lost packets as acknowledged to PacketSenders
opkt . sender - > PacketAcknowledged ( opkt . seq , opkt . sendTime , recvTS / 1000.0f , opkt . type , opkt . size ) ;
2017-02-02 17:24:40 +01:00
}
2019-04-15 01:43:10 +02:00
// TODO move this to a PacketSender
conctl - > PacketAcknowledged ( opkt . seq ) ;
2017-02-02 17:24:40 +01:00
}
}
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( peerVersion < 6 )
{
for ( unsigned int i = 0 ; i < queuedPackets . size ( ) ; i + + )
{
QueuedPacket & qp = queuedPackets [ i ] ;
2019-04-15 01:43:10 +02:00
int j ;
2020-01-22 12:43:51 +01:00
bool didAck = false ;
for ( j = 0 ; j < 16 ; j + + )
{
2019-04-15 01:43:10 +02:00
LOGD ( " queued packet %u, seq %u=%u " , i , j , qp . seqs [ j ] ) ;
2020-01-22 12:43:51 +01:00
if ( qp . seqs [ j ] = = 0 )
2019-04-15 01:43:10 +02:00
break ;
2020-01-22 12:43:51 +01:00
int remoteAcksIndex = lastRemoteAckSeq - qp . seqs [ j ] ;
2019-04-15 01:43:10 +02:00
//LOGV("remote acks index %u, value %f", remoteAcksIndex, remoteAcksIndex>=0 && remoteAcksIndex<32 ? remoteAcks[remoteAcksIndex] : -1);
2020-01-22 12:43:51 +01:00
if ( seqgt ( lastRemoteAckSeq , qp . seqs [ j ] ) & & remoteAcksIndex > = 0 & & remoteAcksIndex < 32 )
{
for ( RecentOutgoingPacket & opkt : recentOutgoingPackets )
{
if ( opkt . seq = = qp . seqs [ j ] & & opkt . ackTime > 0 )
{
2019-04-15 01:43:10 +02:00
LOGD ( " did ack seq %u, removing " , qp . seqs [ j ] ) ;
2020-01-22 12:43:51 +01:00
didAck = true ;
2019-04-15 01:43:10 +02:00
break ;
}
}
2020-01-22 12:43:51 +01:00
if ( didAck )
2019-04-15 01:43:10 +02:00
break ;
2019-02-05 12:41:00 +01:00
}
}
2020-01-22 12:43:51 +01:00
if ( didAck )
{
queuedPackets . erase ( queuedPackets . begin ( ) + i ) ;
2019-04-15 01:43:10 +02:00
i - - ;
continue ;
}
2019-02-05 12:41:00 +01:00
}
2020-01-22 12:43:51 +01:00
}
else
{
for ( auto x = currentExtras . begin ( ) ; x ! = currentExtras . end ( ) ; )
{
if ( x - > firstContainingSeq ! = 0 & & ( lastRemoteAckSeq = = x - > firstContainingSeq | | seqgt ( lastRemoteAckSeq , x - > firstContainingSeq ) ) )
{
2019-04-15 01:43:10 +02:00
LOGV ( " Peer acknowledged extra type %u length %u " , x - > type , ( unsigned int ) x - > data . Length ( ) ) ;
ProcessAcknowledgedOutgoingExtra ( * x ) ;
2020-01-22 12:43:51 +01:00
x = currentExtras . erase ( x ) ;
2019-04-15 01:43:10 +02:00
continue ;
2019-02-05 12:41:00 +01:00
}
2019-04-15 01:43:10 +02:00
+ + x ;
2019-02-05 12:41:00 +01:00
}
}
2018-05-15 20:23:46 +02:00
}
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
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 ( seqgt ( lastSentSeq - 32 , lastRemoteAckSeq ) )
{
currentEndpoint = srcEndpoint . id ;
_currentEndpoint = & srcEndpoint ;
2018-05-15 20:23:46 +02:00
LOGI ( " Peer network address probably changed, switching to relay " ) ;
2020-01-22 12:43:51 +01:00
if ( allowP2p )
2018-05-15 20:23:46 +02:00
SendPublicEndpointsRequest ( ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( config . logPacketStats )
{
DebugLoggedPacket dpkt = {
static_cast < int32_t > ( pseq ) ,
GetCurrentTime ( ) - connectionInitTime ,
static_cast < int32_t > ( packet . data . Length ( ) ) } ;
2018-11-29 01:03:15 +01:00
debugLoggedPackets . push_back ( dpkt ) ;
2020-01-22 12:43:51 +01:00
if ( debugLoggedPackets . size ( ) > = 2500 )
{
debugLoggedPackets . erase ( debugLoggedPackets . begin ( ) , debugLoggedPackets . begin ( ) + 500 ) ;
2018-11-29 01:03:15 +01:00
}
}
2019-04-15 01:43:10 +02:00
unacknowledgedIncomingPacketCount + + ;
2020-01-22 12:43:51 +01:00
if ( unacknowledgedIncomingPacketCount > unackNopThreshold )
{
2019-04-15 01:43:10 +02:00
//LOGV("Sending nop packet as ack");
SendNopPacket ( ) ;
}
2018-12-16 15:41:51 +01:00
# ifdef LOG_PACKETS
2019-04-15 01:43:10 +02:00
LOGV ( " Received: from=%s:%u, seq=%u, length=%u, type=%s " , srcEndpoint . GetAddress ( ) . ToString ( ) . c_str ( ) , srcEndpoint . port , pseq , ( unsigned int ) packet . data . Length ( ) , GetPacketTypeString ( type ) . c_str ( ) ) ;
2018-12-16 15:41:51 +01:00
# endif
2018-05-15 20:23:46 +02:00
//LOGV("acks: %u -> %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf", lastRemoteAckSeq, remoteAcks[0], remoteAcks[1], remoteAcks[2], remoteAcks[3], remoteAcks[4], remoteAcks[5], remoteAcks[6], remoteAcks[7]);
//LOGD("recv: %u -> %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf, %.2lf", lastRemoteSeq, recvPacketTimes[0], recvPacketTimes[1], recvPacketTimes[2], recvPacketTimes[3], recvPacketTimes[4], recvPacketTimes[5], recvPacketTimes[6], recvPacketTimes[7]);
//LOGI("RTT = %.3lf", GetAverageRTT());
//LOGV("Packet %u type is %d", pseq, type);
2020-01-22 12:43:51 +01:00
if ( type = = PKT_INIT )
{
2018-05-15 20:23:46 +02:00
LOGD ( " Received init " ) ;
2020-01-22 12:43:51 +01:00
uint32_t ver = ( uint32_t ) in . ReadInt32 ( ) ;
if ( ! receivedInit )
peerVersion = ver ;
2018-09-04 17:09:50 +02:00
LOGI ( " Peer version is %d " , peerVersion ) ;
2020-01-22 12:43:51 +01:00
uint32_t minVer = ( uint32_t ) in . ReadInt32 ( ) ;
if ( minVer > PROTOCOL_VERSION | | peerVersion < MIN_PROTOCOL_VERSION )
{
lastError = ERROR_INCOMPATIBLE ;
2017-05-09 22:26:18 +02:00
2018-09-04 17:09:50 +02:00
SetState ( STATE_FAILED ) ;
return ;
}
2020-01-22 12:43:51 +01:00
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
if ( ! receivedInit )
{
if ( flags & INIT_FLAG_DATA_SAVING_ENABLED )
{
dataSavingRequestedByPeer = true ;
2018-08-03 16:26:00 +02:00
UpdateDataSavingState ( ) ;
UpdateAudioBitrateLimit ( ) ;
}
2020-01-22 12:43:51 +01:00
if ( flags & INIT_FLAG_GROUP_CALLS_SUPPORTED )
{
peerCapabilities | = TGVOIP_PEER_CAP_GROUP_CALLS ;
2018-08-03 16:26:00 +02:00
}
2020-01-22 12:43:51 +01:00
if ( flags & INIT_FLAG_VIDEO_RECV_SUPPORTED )
{
peerCapabilities | = TGVOIP_PEER_CAP_VIDEO_DISPLAY ;
2019-02-05 12:41:00 +01:00
}
2020-01-22 12:43:51 +01:00
if ( flags & INIT_FLAG_VIDEO_SEND_SUPPORTED )
{
peerCapabilities | = TGVOIP_PEER_CAP_VIDEO_CAPTURE ;
2019-02-05 12:41:00 +01:00
}
2018-09-04 17:09:50 +02:00
}
2017-05-09 22:26:18 +02:00
2018-09-04 17:09:50 +02:00
unsigned int i ;
2020-01-22 12:43:51 +01:00
unsigned int numSupportedAudioCodecs = in . ReadByte ( ) ;
for ( i = 0 ; i < numSupportedAudioCodecs ; i + + )
{
if ( peerVersion < 5 )
2018-09-04 17:09:50 +02:00
in . ReadByte ( ) ; // ignore for now
else
in . ReadInt32 ( ) ;
}
2020-01-22 12:43:51 +01:00
if ( ! receivedInit & & ( ( flags & INIT_FLAG_VIDEO_SEND_SUPPORTED & & config . enableVideoReceive ) | | ( flags & INIT_FLAG_VIDEO_RECV_SUPPORTED & & config . enableVideoSend ) ) )
{
2019-02-05 12:41:00 +01:00
LOGD ( " Peer video decoders: " ) ;
2020-01-22 12:43:51 +01:00
unsigned int numSupportedVideoDecoders = in . ReadByte ( ) ;
for ( i = 0 ; i < numSupportedVideoDecoders ; i + + )
{
uint32_t id = static_cast < uint32_t > ( in . ReadInt32 ( ) ) ;
2019-02-05 12:41:00 +01:00
peerVideoDecoders . push_back ( id ) ;
2020-01-22 12:43:51 +01:00
char * _id = reinterpret_cast < char * > ( & id ) ;
2019-02-05 12:41:00 +01:00
LOGD ( " %c%c%c%c " , _id [ 3 ] , _id [ 2 ] , _id [ 1 ] , _id [ 0 ] ) ;
}
2020-01-22 12:43:51 +01:00
protocolInfo . maxVideoResolution = in . ReadByte ( ) ;
2019-02-05 12:41:00 +01:00
SetupOutgoingVideoStream ( ) ;
2018-09-04 17:09:50 +02:00
}
2018-05-15 20:23:46 +02:00
2018-09-04 17:09:50 +02:00
BufferOutputStream out ( 1024 ) ;
2018-05-15 20:23:46 +02:00
2018-09-04 17:09:50 +02:00
out . WriteInt32 ( PROTOCOL_VERSION ) ;
out . WriteInt32 ( MIN_PROTOCOL_VERSION ) ;
2018-05-15 20:23:46 +02:00
2020-01-22 12:43:51 +01:00
out . WriteByte ( ( unsigned char ) outgoingStreams . size ( ) ) ;
for ( vector < shared_ptr < Stream > > : : iterator s = outgoingStreams . begin ( ) ; s ! = outgoingStreams . end ( ) ; + + s )
{
2018-09-04 17:09:50 +02:00
out . WriteByte ( ( * s ) - > id ) ;
out . WriteByte ( ( * s ) - > type ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion < 5 )
out . WriteByte ( ( unsigned char ) ( ( * s ) - > codec = = CODEC_OPUS ? CODEC_OPUS_OLD : 0 ) ) ;
2018-09-04 17:09:50 +02:00
else
out . WriteInt32 ( ( * s ) - > codec ) ;
out . WriteInt16 ( ( * s ) - > frameDuration ) ;
2020-01-22 12:43:51 +01:00
out . WriteByte ( ( unsigned char ) ( ( * s ) - > enabled ? 1 : 0 ) ) ;
2018-09-04 17:09:50 +02:00
}
LOGI ( " Sending init ack " ) ;
2019-10-27 19:00:16 +01:00
size_t outLength = out . GetLength ( ) ;
2018-11-09 16:44:01 +01:00
SendOrEnqueuePacket ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_INIT_ACK ,
/*.len=*/ outLength ,
/*.data=*/ Buffer ( move ( out ) ) ,
/*.endpoint=*/ 0 } ) ;
if ( ! receivedInit )
{
receivedInit = true ;
if ( ( srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY & & udpConnectivityState ! = UDP_BAD & & udpConnectivityState ! = UDP_NOT_AVAILABLE ) | | srcEndpoint . type = = Endpoint : : Type : : TCP_RELAY )
{
currentEndpoint = srcEndpoint . id ;
if ( srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY | | ( useTCP & & srcEndpoint . type = = Endpoint : : Type : : TCP_RELAY ) )
preferredRelay = srcEndpoint . id ;
2017-02-02 17:24:40 +01:00
}
}
2020-01-22 12:43:51 +01:00
if ( ! audioStarted & & receivedInitAck )
{
2019-01-09 21:22:10 +01:00
StartAudio ( ) ;
2020-01-22 12:43:51 +01:00
audioStarted = true ;
2019-01-09 21:22:10 +01:00
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_INIT_ACK )
{
2018-05-15 20:23:46 +02:00
LOGD ( " Received init ack " ) ;
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
if ( ! receivedInitAck )
{
receivedInitAck = true ;
2018-07-17 18:48:21 +02:00
messageThread . Cancel ( initTimeoutID ) ;
2020-01-22 12:43:51 +01:00
initTimeoutID = MessageThread : : INVALID_ID ;
2018-07-17 18:48:21 +02:00
2020-01-22 12:43:51 +01:00
if ( packetInnerLen > 10 )
{
peerVersion = in . ReadInt32 ( ) ;
uint32_t minVer = ( uint32_t ) in . ReadInt32 ( ) ;
if ( minVer > PROTOCOL_VERSION | | peerVersion < MIN_PROTOCOL_VERSION )
{
lastError = ERROR_INCOMPATIBLE ;
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
SetState ( STATE_FAILED ) ;
return ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
}
else
{
peerVersion = 1 ;
2018-05-15 20:23:46 +02:00
}
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
LOGI ( " peer version from init ack %d " , peerVersion ) ;
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
unsigned char streamCount = in . ReadByte ( ) ;
if ( streamCount = = 0 )
2018-05-15 20:23:46 +02:00
return ;
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
int i ;
2020-01-22 12:43:51 +01:00
shared_ptr < Stream > incomingAudioStream = NULL ;
for ( i = 0 ; i < streamCount ; i + + )
{
shared_ptr < Stream > stm = make_shared < Stream > ( ) ;
stm - > id = in . ReadByte ( ) ;
stm - > type = in . ReadByte ( ) ;
if ( peerVersion < 5 )
{
unsigned char codec = in . ReadByte ( ) ;
if ( codec = = CODEC_OPUS_OLD )
stm - > codec = CODEC_OPUS ;
}
else
{
stm - > codec = ( uint32_t ) in . ReadInt32 ( ) ;
2018-06-04 21:37:43 +02:00
}
2019-01-09 21:22:10 +01:00
in . ReadInt16 ( ) ;
2020-01-22 12:43:51 +01:00
stm - > frameDuration = 60 ;
stm - > enabled = in . ReadByte ( ) = = 1 ;
if ( stm - > type = = STREAM_TYPE_VIDEO & & peerVersion < 9 )
{
2019-03-11 12:31:32 +01:00
LOGV ( " Skipping video stream for old protocol version " ) ;
continue ;
}
2020-01-22 12:43:51 +01:00
if ( stm - > type = = STREAM_TYPE_AUDIO )
{
stm - > jitterBuffer = make_shared < JitterBuffer > ( stm - > frameDuration ) ;
if ( stm - > frameDuration > 50 )
stm - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_60 " , 2 ) ) ;
else if ( stm - > frameDuration > 30 )
stm - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_40 " , 4 ) ) ;
2018-06-04 21:37:43 +02:00
else
2020-01-22 12:43:51 +01:00
stm - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_20 " , 6 ) ) ;
stm - > decoder = NULL ;
}
else if ( stm - > type = = STREAM_TYPE_VIDEO )
{
if ( ! stm - > packetReassembler )
{
stm - > packetReassembler = make_shared < PacketReassembler > ( ) ;
2019-04-15 01:43:10 +02:00
stm - > packetReassembler - > SetCallback ( bind ( & VoIPController : : ProcessIncomingVideoFrame , this , placeholders : : _1 , placeholders : : _2 , placeholders : : _3 , placeholders : : _4 ) ) ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
}
else
{
2018-06-04 21:37:43 +02:00
LOGW ( " Unknown incoming stream type: %d " , stm - > type ) ;
continue ;
2017-03-30 16:06:59 +02:00
}
2018-05-15 20:23:46 +02:00
incomingStreams . push_back ( stm ) ;
2020-01-22 12:43:51 +01:00
if ( stm - > type = = STREAM_TYPE_AUDIO & & ! incomingAudioStream )
incomingAudioStream = stm ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( ! incomingAudioStream )
2018-05-15 20:23:46 +02:00
return ;
2017-05-09 22:26:18 +02:00
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 5 & & ! useMTProto2 )
{
useMTProto2 = true ;
2018-05-15 20:23:46 +02:00
LOGD ( " MTProto2 wasn't initially enabled for whatever reason but peer supports it; upgrading " ) ;
}
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
if ( ! audioStarted & & receivedInit )
{
2018-11-09 16:44:01 +01:00
StartAudio ( ) ;
2020-01-22 12:43:51 +01:00
audioStarted = true ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
messageThread . Post (
[ this ] {
if ( state = = STATE_WAIT_INIT_ACK )
{
SetState ( STATE_ESTABLISHED ) ;
}
} ,
ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " established_delay_if_no_stream_data " , 1.5 ) ) ;
if ( allowP2p )
2018-05-15 20:23:46 +02:00
SendPublicEndpointsRequest ( ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_STREAM_DATA | | type = = PKT_STREAM_DATA_X2 | | type = = PKT_STREAM_DATA_X3 )
{
if ( ! receivedFirstStreamPacket )
{
receivedFirstStreamPacket = true ;
if ( state ! = STATE_ESTABLISHED & & receivedInitAck )
{
messageThread . Post (
[ this ] ( ) {
SetState ( STATE_ESTABLISHED ) ;
} ,
.5 ) ;
2018-08-03 16:26:00 +02:00
LOGW ( " First audio packet - setting state to ESTABLISHED " ) ;
}
}
2018-05-15 20:23:46 +02:00
int count ;
2020-01-22 12:43:51 +01:00
switch ( type )
{
case PKT_STREAM_DATA_X2 :
count = 2 ;
break ;
case PKT_STREAM_DATA_X3 :
count = 3 ;
break ;
case PKT_STREAM_DATA :
default :
count = 1 ;
break ;
2018-05-15 20:23:46 +02:00
}
int i ;
2020-01-22 12:43:51 +01:00
if ( srcEndpoint . type = = Endpoint : : Type : : UDP_RELAY & & srcEndpoint . id ! = peerPreferredRelay )
{
peerPreferredRelay = srcEndpoint . id ;
}
for ( i = 0 ; i < count ; i + + )
{
unsigned char streamID = in . ReadByte ( ) ;
unsigned char flags = ( unsigned char ) ( streamID & 0xC0 ) ;
streamID & = 0x3F ;
uint16_t sdlen = ( uint16_t ) ( flags & STREAM_DATA_FLAG_LEN16 ? in . ReadInt16 ( ) : in . ReadByte ( ) ) ;
uint32_t pts = ( uint32_t ) in . ReadInt32 ( ) ;
unsigned char fragmentCount = 1 ;
unsigned char fragmentIndex = 0 ;
2018-05-15 20:23:46 +02:00
//LOGD("stream data, pts=%d, len=%d, rem=%d", pts, sdlen, in.Remaining());
2020-01-22 12:43:51 +01:00
audioTimestampIn = pts ;
if ( ! audioOutStarted & & audioOutput )
{
2018-06-01 22:06:04 +02:00
MutexGuard m ( audioIOMutex ) ;
2018-05-15 20:23:46 +02:00
audioOutput - > Start ( ) ;
2020-01-22 12:43:51 +01:00
audioOutStarted = true ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
bool fragmented = static_cast < bool > ( sdlen & STREAM_DATA_XFLAG_FRAGMENTED ) ;
bool extraFEC = static_cast < bool > ( sdlen & STREAM_DATA_XFLAG_EXTRA_FEC ) ;
bool keyframe = static_cast < bool > ( sdlen & STREAM_DATA_XFLAG_KEYFRAME ) ;
if ( fragmented )
{
fragmentIndex = in . ReadByte ( ) ;
fragmentCount = in . ReadByte ( ) ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
sdlen & = 0x7FF ;
if ( in . GetOffset ( ) + sdlen > len )
{
2018-05-15 20:23:46 +02:00
return ;
2017-04-09 18:14:33 +02:00
}
2018-11-09 16:44:01 +01:00
shared_ptr < Stream > stm ;
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & ss : incomingStreams )
{
if ( ss - > id = = streamID )
{
stm = ss ;
2018-11-09 16:44:01 +01:00
break ;
}
}
2020-01-22 12:43:51 +01:00
if ( stm & & stm - > type = = STREAM_TYPE_AUDIO )
{
if ( stm - > jitterBuffer )
{
stm - > jitterBuffer - > HandleInput ( static_cast < unsigned char * > ( buffer + in . GetOffset ( ) ) , sdlen , pts , false ) ;
if ( extraFEC )
{
in . Seek ( in . GetOffset ( ) + sdlen ) ;
unsigned int fecCount = in . ReadByte ( ) ;
for ( unsigned int j = 0 ; j < fecCount ; j + + )
{
unsigned char dlen = in . ReadByte ( ) ;
2018-11-09 16:44:01 +01:00
unsigned char data [ 256 ] ;
in . ReadBytes ( data , dlen ) ;
2020-01-22 12:43:51 +01:00
stm - > jitterBuffer - > HandleInput ( data , dlen , pts - ( fecCount - j - 1 ) * stm - > frameDuration , true ) ;
2018-11-09 16:44:01 +01:00
}
}
}
2020-01-22 12:43:51 +01:00
}
else if ( stm & & stm - > type = = STREAM_TYPE_VIDEO )
{
if ( stm - > packetReassembler )
{
uint8_t frameSeq = in . ReadByte ( ) ;
2018-11-09 16:44:01 +01:00
Buffer pdata ( sdlen ) ;
2020-01-22 12:43:51 +01:00
uint16_t rotation = 0 ;
if ( fragmentIndex = = 0 )
{
unsigned char _rotation = in . ReadByte ( ) & ( unsigned char ) VIDEO_ROTATION_MASK ;
switch ( _rotation )
{
case VIDEO_ROTATION_0 :
rotation = 0 ;
break ;
case VIDEO_ROTATION_90 :
rotation = 90 ;
break ;
case VIDEO_ROTATION_180 :
rotation = 180 ;
break ;
case VIDEO_ROTATION_270 :
rotation = 270 ;
break ;
default : // unreachable on sane CPUs
abort ( ) ;
2019-04-15 01:43:10 +02:00
}
//if(rotation!=stm->rotation){
// stm->rotation=rotation;
// LOGI("Video rotation: %u", rotation);
//}
}
2020-01-22 12:43:51 +01:00
pdata . CopyFrom ( buffer + in . GetOffset ( ) , 0 , sdlen ) ;
2019-04-15 01:43:10 +02:00
stm - > packetReassembler - > AddFragment ( std : : move ( pdata ) , fragmentIndex , fragmentCount , pts , frameSeq , keyframe , rotation ) ;
2018-11-09 16:44:01 +01:00
}
//LOGV("Received video fragment %u of %u", fragmentIndex, fragmentCount);
2020-01-22 12:43:51 +01:00
}
else
{
2018-11-09 16:44:01 +01:00
LOGW ( " received packet for unknown stream %u " , ( unsigned int ) streamID ) ;
}
2020-01-22 12:43:51 +01:00
if ( i < count - 1 )
in . Seek ( in . GetOffset ( ) + sdlen ) ;
2018-05-15 20:23:46 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_PING )
{
2018-11-09 16:44:01 +01:00
//LOGD("Received ping from %s:%d", srcEndpoint.address.ToString().c_str(), srcEndpoint.port);
2020-01-22 12:43:51 +01:00
if ( srcEndpoint . type ! = Endpoint : : Type : : UDP_RELAY & & srcEndpoint . type ! = Endpoint : : Type : : TCP_RELAY & & ! allowP2p )
{
2018-05-15 20:23:46 +02:00
LOGW ( " Received p2p ping but p2p is disabled by manual override " ) ;
return ;
}
2018-08-07 22:10:31 +02:00
BufferOutputStream pkt ( 128 ) ;
2018-05-15 20:23:46 +02:00
pkt . WriteInt32 ( pseq ) ;
2019-10-27 19:00:16 +01:00
size_t pktLength = pkt . GetLength ( ) ;
2018-11-09 16:44:01 +01:00
SendOrEnqueuePacket ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_PONG ,
/*.len=*/ pktLength ,
/*.data=*/ Buffer ( move ( pkt ) ) ,
/*.endpoint=*/ srcEndpoint . id ,
2018-05-15 20:23:46 +02:00
} ) ;
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_PONG )
{
if ( packetInnerLen > = 4 )
{
uint32_t pingSeq = ( uint32_t ) in . ReadInt32 ( ) ;
2018-12-16 15:41:51 +01:00
# ifdef LOG_PACKETS
LOGD ( " Received pong for ping in seq %u " , pingSeq ) ;
# endif
2020-01-22 12:43:51 +01:00
if ( pingSeq = = srcEndpoint . lastPingSeq )
{
srcEndpoint . rtts . Add ( GetCurrentTime ( ) - srcEndpoint . lastPingTime ) ;
srcEndpoint . averageRTT = srcEndpoint . rtts . NonZeroAverage ( ) ;
2019-04-15 01:43:10 +02:00
LOGD ( " Current RTT via %s: %.3f, average: %.3f " , packet . address . ToString ( ) . c_str ( ) , srcEndpoint . rtts [ 0 ] , srcEndpoint . averageRTT ) ;
2020-01-22 12:43:51 +01:00
if ( srcEndpoint . averageRTT > rateMaxAcceptableRTT )
needRate = true ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_STREAM_STATE )
{
unsigned char id = in . ReadByte ( ) ;
unsigned char enabled = in . ReadByte ( ) ;
2018-11-09 16:44:01 +01:00
LOGV ( " Peer stream state: id %u flags %u " , ( int ) id , ( int ) enabled ) ;
2020-01-22 12:43:51 +01:00
for ( vector < shared_ptr < Stream > > : : iterator s = incomingStreams . begin ( ) ; s ! = incomingStreams . end ( ) ; + + s )
{
if ( ( * s ) - > id = = id )
{
( * s ) - > enabled = enabled = = 1 ;
2018-05-15 20:23:46 +02:00
UpdateAudioOutputState ( ) ;
break ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_LAN_ENDPOINT )
{
2018-05-15 20:23:46 +02:00
LOGV ( " received lan endpoint " ) ;
2020-01-22 12:43:51 +01:00
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 ;
2018-11-09 16:44:01 +01:00
unsigned char peerTag [ 16 ] ;
2019-04-15 01:43:10 +02:00
Endpoint lan ( lanID , peerPort , NetworkAddress : : IPv4 ( peerAddr ) , NetworkAddress : : Empty ( ) , Endpoint : : Type : : UDP_P2P_LAN , peerTag ) ;
2018-11-09 16:44:01 +01:00
2020-01-22 12:43:51 +01:00
if ( currentEndpoint = = lanID )
currentEndpoint = preferredRelay ;
2019-04-15 01:43:10 +02:00
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
endpoints [ lanID ] = lan ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_NETWORK_CHANGED & & _currentEndpoint - > type ! = Endpoint : : Type : : UDP_RELAY & & _currentEndpoint - > type ! = Endpoint : : Type : : TCP_RELAY )
{
currentEndpoint = preferredRelay ;
if ( allowP2p )
2018-05-15 20:23:46 +02:00
SendPublicEndpointsRequest ( ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 2 )
{
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
dataSavingRequestedByPeer = ( flags & INIT_FLAG_DATA_SAVING_ENABLED ) = = INIT_FLAG_DATA_SAVING_ENABLED ;
2018-05-15 20:23:46 +02:00
UpdateDataSavingState ( ) ;
2018-07-17 18:48:21 +02:00
UpdateAudioBitrateLimit ( ) ;
2018-08-24 01:29:07 +02:00
ResetEndpointPingStats ( ) ;
2018-05-15 20:23:46 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( type = = PKT_STREAM_EC )
{
unsigned char streamID = in . ReadByte ( ) ;
if ( peerVersion < 7 )
{
uint32_t lastTimestamp = ( uint32_t ) in . ReadInt32 ( ) ;
unsigned char count = in . ReadByte ( ) ;
for ( shared_ptr < Stream > & stm : incomingStreams )
{
if ( stm - > id = = streamID )
{
for ( unsigned int i = 0 ; i < count ; i + + )
{
unsigned char dlen = in . ReadByte ( ) ;
2019-04-15 01:43:10 +02:00
unsigned char data [ 256 ] ;
in . ReadBytes ( data , dlen ) ;
2020-01-22 12:43:51 +01:00
if ( stm - > jitterBuffer )
{
stm - > jitterBuffer - > HandleInput ( data , dlen , lastTimestamp - ( count - i - 1 ) * stm - > frameDuration , true ) ;
2019-04-15 01:43:10 +02:00
}
2018-06-04 21:37:43 +02:00
}
2019-04-15 01:43:10 +02:00
break ;
2018-06-04 21:37:43 +02:00
}
}
2020-01-22 12:43:51 +01:00
}
else
{
shared_ptr < Stream > stm = GetStreamByID ( streamID , false ) ;
if ( ! stm )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Received FEC packet for unknown stream %u " , streamID ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( stm - > type ! = STREAM_TYPE_VIDEO )
{
2019-04-15 01:43:10 +02:00
LOGW ( " Received FEC packet for non-video stream %u " , streamID ) ;
return ;
}
2020-01-22 12:43:51 +01:00
if ( ! stm - > packetReassembler )
2019-04-15 01:43:10 +02:00
return ;
2020-01-22 12:43:51 +01:00
uint8_t fseq = in . ReadByte ( ) ;
unsigned char fecScheme = in . ReadByte ( ) ;
unsigned char prevFrameCount = in . ReadByte ( ) ;
uint16_t fecLen = ( uint16_t ) in . ReadInt16 ( ) ;
if ( fecLen > in . Remaining ( ) )
2019-04-15 01:43:10 +02:00
return ;
Buffer fecData ( fecLen ) ;
in . ReadBytes ( fecData ) ;
stm - > packetReassembler - > AddFEC ( std : : move ( fecData ) , fseq , prevFrameCount , fecScheme ) ;
2018-06-04 21:37:43 +02:00
}
2018-05-15 20:23:46 +02:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ProcessExtraData ( Buffer & data )
{
2018-06-04 21:37:43 +02:00
BufferInputStream in ( * data , data . Length ( ) ) ;
2020-01-22 12:43:51 +01:00
unsigned char type = in . ReadByte ( ) ;
2018-06-04 21:37:43 +02:00
unsigned char fullHash [ SHA1_LENGTH ] ;
crypto . sha1 ( * data , data . Length ( ) , fullHash ) ;
2020-01-22 12:43:51 +01:00
uint64_t hash = * reinterpret_cast < uint64_t * > ( fullHash ) ;
if ( lastReceivedExtrasByType [ type ] = = hash )
{
2018-05-15 20:23:46 +02:00
return ;
}
2019-02-05 12:41:00 +01:00
LOGE ( " ProcessExtraData " ) ;
2020-01-22 12:43:51 +01:00
lastReceivedExtrasByType [ type ] = hash ;
if ( type = = EXTRA_TYPE_STREAM_FLAGS )
{
unsigned char id = in . ReadByte ( ) ;
uint32_t flags = static_cast < uint32_t > ( in . ReadInt32 ( ) ) ;
2018-11-09 16:44:01 +01:00
LOGV ( " Peer stream state: id %u flags %u " , ( unsigned int ) id , ( unsigned int ) flags ) ;
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & s : incomingStreams )
{
if ( s - > id = = id )
{
bool prevEnabled = s - > enabled ;
bool prevPaused = s - > paused ;
s - > enabled = ( flags & STREAM_FLAG_ENABLED ) = = STREAM_FLAG_ENABLED ;
s - > paused = ( flags & STREAM_FLAG_PAUSED ) = = STREAM_FLAG_PAUSED ;
if ( flags & STREAM_FLAG_EXTRA_EC )
{
if ( ! s - > extraECEnabled )
{
s - > extraECEnabled = true ;
if ( s - > jitterBuffer )
2018-06-04 21:37:43 +02:00
s - > jitterBuffer - > SetMinPacketCount ( 4 ) ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
}
else
{
if ( s - > extraECEnabled )
{
s - > extraECEnabled = false ;
if ( s - > jitterBuffer )
2018-06-04 21:37:43 +02:00
s - > jitterBuffer - > SetMinPacketCount ( 2 ) ;
2017-02-02 17:24:40 +01:00
}
}
2020-01-22 12:43:51 +01:00
if ( prevEnabled ! = s - > enabled & & s - > type = = STREAM_TYPE_VIDEO & & videoRenderer )
2019-02-05 12:41:00 +01:00
videoRenderer - > SetStreamEnabled ( s - > enabled ) ;
2020-01-22 12:43:51 +01:00
if ( prevPaused ! = s - > paused & & s - > type = = STREAM_TYPE_VIDEO & & videoRenderer )
2019-04-15 01:43:10 +02:00
videoRenderer - > SetStreamPaused ( s - > paused ) ;
2018-06-04 21:37:43 +02:00
UpdateAudioOutputState ( ) ;
break ;
2017-02-02 17:24:40 +01:00
}
}
2020-01-22 12:43:51 +01:00
}
else if ( type = = EXTRA_TYPE_STREAM_CSD )
{
2018-11-09 16:44:01 +01:00
LOGI ( " Received codec specific data " ) ;
/*
os . WriteByte ( stream . id ) ;
os . WriteByte ( static_cast < unsigned char > ( stream . codecSpecificData . size ( ) ) ) ;
for ( Buffer & b : stream . codecSpecificData ) {
assert ( b . Length ( ) < 255 ) ;
os . WriteByte ( static_cast < unsigned char > ( b . Length ( ) ) ) ;
os . WriteBytes ( b ) ;
}
Buffer buf ( move ( os ) ) ;
SendExtra ( buf , EXTRA_TYPE_STREAM_CSD ) ;
*/
2020-01-22 12:43:51 +01:00
unsigned char streamID = in . ReadByte ( ) ;
for ( shared_ptr < Stream > & stm : incomingStreams )
{
if ( stm - > id = = streamID )
{
2018-11-09 16:44:01 +01:00
stm - > codecSpecificData . clear ( ) ;
2020-01-22 12:43:51 +01:00
stm - > csdIsValid = false ;
stm - > width = static_cast < unsigned int > ( in . ReadInt16 ( ) ) ;
stm - > height = static_cast < unsigned int > ( in . ReadInt16 ( ) ) ;
size_t count = ( size_t ) in . ReadByte ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
size_t len = ( size_t ) in . ReadByte ( ) ;
2018-11-09 16:44:01 +01:00
Buffer csd ( len ) ;
in . ReadBytes ( * csd , len ) ;
stm - > codecSpecificData . push_back ( move ( csd ) ) ;
}
break ;
}
}
2020-01-22 12:43:51 +01:00
}
else if ( type = = EXTRA_TYPE_LAN_ENDPOINT )
{
if ( ! allowP2p )
2018-06-04 21:37:43 +02:00
return ;
LOGV ( " received lan endpoint (extra) " ) ;
2020-01-22 12:43:51 +01:00
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 ;
if ( currentEndpoint = = lanID )
currentEndpoint = preferredRelay ;
2018-11-09 16:44:01 +01:00
unsigned char peerTag [ 16 ] ;
2019-04-15 01:43:10 +02:00
Endpoint lan ( lanID , peerPort , NetworkAddress : : IPv4 ( peerAddr ) , NetworkAddress : : Empty ( ) , Endpoint : : Type : : UDP_P2P_LAN , peerTag ) ;
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
endpoints [ lanID ] = lan ;
}
else if ( type = = EXTRA_TYPE_NETWORK_CHANGED )
{
2018-08-24 01:29:07 +02:00
LOGI ( " Peer network changed " ) ;
2020-01-22 12:43:51 +01:00
wasNetworkHandover = true ;
const Endpoint & _currentEndpoint = endpoints . at ( currentEndpoint ) ;
if ( _currentEndpoint . type ! = Endpoint : : Type : : UDP_RELAY & & _currentEndpoint . type ! = Endpoint : : Type : : TCP_RELAY )
currentEndpoint = preferredRelay ;
if ( allowP2p )
2018-08-24 01:29:07 +02:00
SendPublicEndpointsRequest ( ) ;
2020-01-22 12:43:51 +01:00
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
dataSavingRequestedByPeer = ( flags & INIT_FLAG_DATA_SAVING_ENABLED ) = = INIT_FLAG_DATA_SAVING_ENABLED ;
2018-08-24 01:29:07 +02:00
UpdateDataSavingState ( ) ;
UpdateAudioBitrateLimit ( ) ;
ResetEndpointPingStats ( ) ;
2020-01-22 12:43:51 +01:00
}
else if ( type = = EXTRA_TYPE_GROUP_CALL_KEY )
{
if ( ! didReceiveGroupCallKey & & ! didSendGroupCallKey )
{
2018-06-04 21:37:43 +02:00
unsigned char groupKey [ 256 ] ;
in . ReadBytes ( groupKey , 256 ) ;
2020-01-22 12:43:51 +01:00
messageThread . Post ( [ this , & groupKey ] {
if ( callbacks . groupCallKeyReceived )
2018-07-17 18:48:21 +02:00
callbacks . groupCallKeyReceived ( this , groupKey ) ;
} ) ;
2020-01-22 12:43:51 +01:00
didReceiveGroupCallKey = true ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
}
else if ( type = = EXTRA_TYPE_REQUEST_GROUP )
{
if ( ! didInvokeUpgradeCallback )
{
messageThread . Post ( [ this ] {
if ( callbacks . upgradeToGroupCallRequested )
2018-07-17 18:48:21 +02:00
callbacks . upgradeToGroupCallRequested ( this ) ;
} ) ;
2020-01-22 12:43:51 +01:00
didInvokeUpgradeCallback = true ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
}
else if ( type = = EXTRA_TYPE_IPV6_ENDPOINT )
{
if ( ! allowP2p )
2018-06-04 21:37:43 +02:00
return ;
unsigned char _addr [ 16 ] ;
in . ReadBytes ( _addr , 16 ) ;
2020-01-22 12:43:51 +01:00
NetworkAddress addr = NetworkAddress : : IPv6 ( _addr ) ;
uint16_t port = static_cast < uint16_t > ( in . ReadInt16 ( ) ) ;
peerIPv6Available = true ;
2018-11-09 16:44:01 +01:00
LOGV ( " Received peer IPv6 endpoint [%s]:%u " , addr . ToString ( ) . c_str ( ) , port ) ;
2020-01-22 12:43:51 +01:00
constexpr int64_t p2pID = ( int64_t ) ( FOURCC ( ' P ' , ' 2 ' , ' P ' , ' 6 ' ) ) < < 32 ;
2018-11-09 16:44:01 +01:00
Endpoint ep ;
2020-01-22 12:43:51 +01:00
ep . type = Endpoint : : Type : : UDP_P2P_INET ;
ep . port = port ;
ep . v6address = addr ;
ep . id = p2pID ;
endpoints [ p2pID ] = ep ;
if ( ! myIPv6 . IsEmpty ( ) )
currentEndpoint = p2pID ;
}
}
void VoIPController : : ProcessAcknowledgedOutgoingExtra ( UnacknowledgedExtraData & extra )
{
if ( extra . type = = EXTRA_TYPE_GROUP_CALL_KEY )
{
if ( ! didReceiveGroupCallKeyAck )
{
didReceiveGroupCallKeyAck = true ;
messageThread . Post ( [ this ] {
if ( callbacks . groupCallKeySent )
2018-07-17 18:48:21 +02:00
callbacks . groupCallKeySent ( this ) ;
} ) ;
2017-04-28 13:17:56 +02:00
}
2017-02-02 17:24:40 +01:00
}
}
2020-01-22 12:43:51 +01:00
Endpoint & VoIPController : : GetRemoteEndpoint ( )
{
2018-11-09 16:44:01 +01:00
return endpoints . at ( currentEndpoint ) ;
}
2020-01-22 12:43:51 +01:00
Endpoint * VoIPController : : GetEndpointForPacket ( const PendingOutgoingPacket & pkt )
{
Endpoint * endpoint = NULL ;
if ( pkt . endpoint )
{
try
{
endpoint = & endpoints . at ( pkt . endpoint ) ;
}
catch ( out_of_range & x )
{
2018-11-09 16:44:01 +01:00
LOGW ( " Unable to send packet via nonexistent endpoint % " PRIu64 , pkt . endpoint ) ;
return NULL ;
}
}
2020-01-22 12:43:51 +01:00
if ( ! endpoint )
endpoint = & endpoints . at ( currentEndpoint ) ;
2018-11-09 16:44:01 +01:00
return endpoint ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
bool VoIPController : : SendOrEnqueuePacket ( PendingOutgoingPacket pkt , bool enqueue , PacketSender * source )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
Endpoint * endpoint = GetEndpointForPacket ( pkt ) ;
if ( ! endpoint )
{
2018-11-09 16:44:01 +01:00
abort ( ) ;
return false ;
}
2019-12-05 09:06:41 +01:00
2018-11-09 16:44:01 +01:00
bool canSend ;
2020-01-22 12:43:51 +01:00
if ( endpoint - > type ! = Endpoint : : Type : : TCP_RELAY )
{
canSend = realUdpSocket - > IsReadyToSend ( ) ;
}
else
{
if ( ! endpoint - > socket )
{
2018-11-09 16:44:01 +01:00
LOGV ( " Connecting to %s:%u " , endpoint - > GetAddress ( ) . ToString ( ) . c_str ( ) , endpoint - > port ) ;
2020-01-22 12:43:51 +01:00
if ( proxyProtocol = = PROXY_NONE )
{
endpoint - > socket = make_shared < NetworkSocketTCPObfuscated > ( NetworkSocket : : Create ( NetworkProtocol : : TCP ) ) ;
2019-04-15 01:43:10 +02:00
endpoint - > socket - > Connect ( endpoint - > GetAddress ( ) , endpoint - > port ) ;
2020-01-22 12:43:51 +01:00
}
else if ( proxyProtocol = = PROXY_SOCKS5 )
{
NetworkSocket * tcp = NetworkSocket : : Create ( NetworkProtocol : : TCP ) ;
2018-11-09 16:44:01 +01:00
tcp - > Connect ( resolvedProxyAddress , proxyPort ) ;
2020-01-22 12:43:51 +01:00
shared_ptr < NetworkSocketSOCKS5Proxy > proxy = make_shared < NetworkSocketSOCKS5Proxy > ( tcp , nullptr , proxyUsername , proxyPassword ) ;
endpoint - > socket = proxy ;
2019-04-15 01:43:10 +02:00
endpoint - > socket - > Connect ( endpoint - > GetAddress ( ) , endpoint - > port ) ;
2018-11-09 16:44:01 +01:00
}
selectCanceller - > CancelSelect ( ) ;
}
2020-01-22 12:43:51 +01:00
canSend = endpoint - > socket & & endpoint - > socket - > IsReadyToSend ( ) ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
if ( ! canSend )
{
if ( enqueue )
{
LOGW ( " Not ready to send - enqueueing " ) ;
sendQueue . push_back ( move ( pkt ) ) ;
2018-11-09 16:44:01 +01:00
}
return false ;
}
2020-01-22 12:43:51 +01:00
if ( ( endpoint - > type = = Endpoint : : Type : : TCP_RELAY & & useTCP ) | | ( endpoint - > type ! = Endpoint : : Type : : TCP_RELAY & & useUDP ) )
{
2018-11-09 16:44:01 +01:00
//BufferOutputStream p(buf, sizeof(buf));
BufferOutputStream p ( 1500 ) ;
2019-04-15 01:43:10 +02:00
WritePacketHeader ( pkt . seq , & p , pkt . type , ( uint32_t ) pkt . len , source ) ;
2018-11-09 16:44:01 +01:00
p . WriteBytes ( pkt . data ) ;
SendPacket ( p . GetBuffer ( ) , p . GetLength ( ) , * endpoint , pkt ) ;
2020-01-22 12:43:51 +01:00
if ( pkt . type = = PKT_STREAM_DATA )
{
2018-11-09 16:44:01 +01:00
unsentStreamPackets - - ;
}
}
return true ;
}
2017-02-02 17:24:40 +01:00
2020-01-22 12:43:51 +01:00
void VoIPController : : SendPacket ( unsigned char * data , size_t len , Endpoint & ep , PendingOutgoingPacket & srcPacket )
{
if ( stopping )
2017-02-02 17:24:40 +01:00
return ;
2020-01-22 12:43:51 +01:00
if ( ep . type = = Endpoint : : Type : : TCP_RELAY & & ! useTCP )
2017-06-06 03:44:16 +02:00
return ;
2020-01-22 12:43:51 +01:00
BufferOutputStream out ( len + 128 ) ;
if ( ep . type = = Endpoint : : Type : : UDP_RELAY | | ep . type = = Endpoint : : Type : : TCP_RELAY )
out . WriteBytes ( ( unsigned char * ) ep . peerTag , 16 ) ;
else if ( peerVersion < 9 )
2017-02-02 17:24:40 +01:00
out . WriteBytes ( callID , 16 ) ;
2020-01-22 12:43:51 +01:00
if ( len > 0 )
{
if ( useMTProto2 )
{
BufferOutputStream inner ( len + 128 ) ;
2018-11-23 00:46:23 +01:00
size_t sizeSize ;
2020-01-22 12:43:51 +01:00
if ( peerVersion > = 8 | | ( ! peerVersion & & connectionMaxLayer > = 92 ) )
{
inner . WriteInt16 ( ( uint16_t ) len ) ;
sizeSize = 0 ;
}
else
{
inner . WriteInt32 ( ( uint32_t ) len ) ;
2018-11-23 00:46:23 +01:00
out . WriteBytes ( keyFingerprint , 8 ) ;
2020-01-22 12:43:51 +01:00
sizeSize = 4 ;
2018-11-23 00:46:23 +01:00
}
2018-05-15 20:23:46 +02:00
inner . WriteBytes ( data , len ) ;
2018-11-23 00:46:23 +01:00
2020-01-22 12:43:51 +01:00
size_t padLen = 16 - inner . GetLength ( ) % 16 ;
if ( padLen < 16 )
padLen + = 16 ;
2018-11-23 00:46:23 +01:00
unsigned char padding [ 32 ] ;
2020-01-22 12:43:51 +01:00
crypto . rand_bytes ( ( uint8_t * ) padding , padLen ) ;
2017-02-02 17:24:40 +01:00
inner . WriteBytes ( padding , padLen ) ;
2020-01-22 12:43:51 +01:00
assert ( inner . GetLength ( ) % 16 = = 0 ) ;
2018-05-15 20:23:46 +02:00
unsigned char key [ 32 ] , iv [ 32 ] , msgKey [ 16 ] ;
2020-01-22 12:43:51 +01:00
BufferOutputStream buf ( len + 32 ) ;
size_t x = isOutgoing ? 0 : 8 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( inner . GetBuffer ( ) + sizeSize , inner . GetLength ( ) - sizeSize ) ;
2018-05-15 20:23:46 +02:00
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
2020-01-22 12:43:51 +01:00
memcpy ( msgKey , msgKeyLarge + 8 , 16 ) ;
2018-05-15 20:23:46 +02:00
KDF2 ( msgKey , isOutgoing ? 0 : 8 , key , iv ) ;
out . WriteBytes ( msgKey , 16 ) ;
//LOGV("<- MSG KEY: %08x %08x %08x %08x, hashed %u", *reinterpret_cast<int32_t*>(msgKey), *reinterpret_cast<int32_t*>(msgKey+4), *reinterpret_cast<int32_t*>(msgKey+8), *reinterpret_cast<int32_t*>(msgKey+12), inner.GetLength()-4);
unsigned char aesOut [ MSC_STACK_FALLBACK ( inner . GetLength ( ) , 1500 ) ] ;
crypto . aes_ige_encrypt ( inner . GetBuffer ( ) , aesOut , inner . GetLength ( ) , key , iv ) ;
out . WriteBytes ( aesOut , inner . GetLength ( ) ) ;
2020-01-22 12:43:51 +01:00
}
else
{
BufferOutputStream inner ( len + 128 ) ;
2018-11-09 16:44:01 +01:00
inner . WriteInt32 ( ( int32_t ) len ) ;
2018-05-15 20:23:46 +02:00
inner . WriteBytes ( data , len ) ;
2020-01-22 12:43:51 +01:00
if ( inner . GetLength ( ) % 16 ! = 0 )
{
size_t padLen = 16 - inner . GetLength ( ) % 16 ;
2018-05-15 20:23:46 +02:00
unsigned char padding [ 16 ] ;
2020-01-22 12:43:51 +01:00
crypto . rand_bytes ( ( uint8_t * ) padding , padLen ) ;
2018-05-15 20:23:46 +02:00
inner . WriteBytes ( padding , padLen ) ;
}
2020-01-22 12:43:51 +01:00
assert ( inner . GetLength ( ) % 16 = = 0 ) ;
2018-05-15 20:23:46 +02:00
unsigned char key [ 32 ] , iv [ 32 ] , msgHash [ SHA1_LENGTH ] ;
2020-01-22 12:43:51 +01:00
crypto . sha1 ( ( uint8_t * ) inner . GetBuffer ( ) , len + 4 , msgHash ) ;
2018-05-15 20:23:46 +02:00
out . WriteBytes ( keyFingerprint , 8 ) ;
2020-01-22 12:43:51 +01:00
out . WriteBytes ( ( msgHash + ( SHA1_LENGTH - 16 ) ) , 16 ) ;
KDF ( msgHash + ( SHA1_LENGTH - 16 ) , isOutgoing ? 0 : 8 , key , iv ) ;
2018-05-15 20:23:46 +02:00
unsigned char aesOut [ MSC_STACK_FALLBACK ( inner . GetLength ( ) , 1500 ) ] ;
crypto . aes_ige_encrypt ( inner . GetBuffer ( ) , aesOut , inner . GetLength ( ) , key , iv ) ;
out . WriteBytes ( aesOut , inner . GetLength ( ) ) ;
2017-02-02 17:24:40 +01:00
}
}
2018-11-09 16:44:01 +01:00
//LOGV("Sending %d bytes to %s:%d", out.GetLength(), ep.address.ToString().c_str(), ep.port);
2018-12-16 15:41:51 +01:00
# ifdef LOG_PACKETS
2019-04-15 01:43:10 +02:00
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 ( ) ) ;
2018-12-16 15:41:51 +01:00
# endif
2017-04-17 20:57:07 +02:00
2019-04-15 01:43:10 +02:00
/*ActuallySendPacket(NetworkPacket{
Buffer ( std : : move ( out ) ) ,
ep . GetAddress ( ) ,
ep . port ,
ep . type = = Endpoint : : Type : : TCP_RELAY ? NetworkProtocol : : TCP : NetworkProtocol : : UDP
} , ep ) ; */
rawSendQueue . Put ( RawPendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
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 } ) ;
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ActuallySendPacket ( NetworkPacket pkt , Endpoint & ep )
{
2018-05-15 20:23:46 +02:00
//LOGI("Sending packet of %d bytes", pkt.length);
2020-01-22 12:43:51 +01:00
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesSentMobile + = ( uint64_t ) pkt . data . Length ( ) ;
2018-11-18 00:36:55 +01:00
else
2020-01-22 12:43:51 +01:00
stats . bytesSentWifi + = ( uint64_t ) pkt . data . Length ( ) ;
if ( ep . type = = Endpoint : : Type : : TCP_RELAY )
{
if ( ep . socket & & ! ep . socket - > IsFailed ( ) )
{
2019-04-15 01:43:10 +02:00
ep . socket - > Send ( std : : move ( pkt ) ) ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
}
else
{
2019-04-15 01:43:10 +02:00
udpSocket - > Send ( std : : move ( pkt ) ) ;
2018-11-09 16:44:01 +01:00
}
}
2020-01-22 12:43:51 +01:00
std : : string VoIPController : : NetworkTypeToString ( int type )
{
switch ( type )
{
case NET_TYPE_WIFI :
return " wifi " ;
case NET_TYPE_GPRS :
return " gprs " ;
case NET_TYPE_EDGE :
return " edge " ;
case NET_TYPE_3G :
return " 3g " ;
case NET_TYPE_HSPA :
return " hspa " ;
case NET_TYPE_LTE :
return " lte " ;
case NET_TYPE_ETHERNET :
return " ethernet " ;
case NET_TYPE_OTHER_HIGH_SPEED :
return " other_high_speed " ;
case NET_TYPE_OTHER_LOW_SPEED :
return " other_low_speed " ;
case NET_TYPE_DIALUP :
return " dialup " ;
case NET_TYPE_OTHER_MOBILE :
return " other_mobile " ;
default :
return " unknown " ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
2020-01-22 12:43:51 +01:00
std : : string VoIPController : : GetPacketTypeString ( unsigned char type )
{
switch ( type )
{
case PKT_INIT :
return " init " ;
case PKT_INIT_ACK :
return " init_ack " ;
case PKT_STREAM_STATE :
return " stream_state " ;
case PKT_STREAM_DATA :
return " stream_data " ;
case PKT_PING :
return " ping " ;
case PKT_PONG :
return " pong " ;
case PKT_LAN_ENDPOINT :
return " lan_endpoint " ;
case PKT_NETWORK_CHANGED :
return " network_changed " ;
case PKT_NOP :
return " nop " ;
case PKT_STREAM_EC :
return " stream_ec " ;
}
char buf [ 255 ] ;
2018-12-16 15:41:51 +01:00
snprintf ( buf , sizeof ( buf ) , " unknown(%u) " , type ) ;
return string ( buf ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : AddIPv6Relays ( )
{
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( ! myIPv6 . IsEmpty ( ) & & ! didAddIPv6Relays )
{
2018-11-09 16:44:01 +01:00
unordered_map < string , vector < Endpoint > > endpointsByAddress ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & _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 ( ) )
{
2018-11-09 16:44:01 +01:00
endpointsByAddress [ e . v6address . ToString ( ) ] . push_back ( e ) ;
}
}
2019-04-15 01:43:10 +02:00
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const string , vector < Endpoint > > & addr : endpointsByAddress )
{
for ( Endpoint & e : addr . second )
{
didAddIPv6Relays = true ;
e . address = NetworkAddress : : Empty ( ) ;
e . id = e . id ^ ( ( int64_t ) ( FOURCC ( ' I ' , ' P ' , ' v ' , ' 6 ' ) ) < < 32 ) ;
e . averageRTT = 0 ;
e . lastPingSeq = 0 ;
e . lastPingTime = 0 ;
2018-11-09 16:44:01 +01:00
e . rtts . Reset ( ) ;
2020-01-22 12:43:51 +01:00
e . udpPongCount = 0 ;
endpoints [ e . id ] = e ;
2018-11-09 16:44:01 +01:00
LOGD ( " Adding IPv6-only endpoint [%s]:%u " , e . v6address . ToString ( ) . c_str ( ) , e . port ) ;
2018-06-04 21:37:43 +02:00
}
}
2018-05-15 20:23:46 +02:00
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : AddTCPRelays ( )
{
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( ! didAddTcpRelays )
{
bool wasSetCurrentToTCP = setCurrentEndpointToTCP ;
2019-02-05 12:41:00 +01:00
LOGV ( " Adding TCP relays " ) ;
2018-11-09 16:44:01 +01:00
vector < Endpoint > relays ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
if ( e . type ! = Endpoint : : Type : : UDP_RELAY )
2018-07-17 18:48:21 +02:00
continue ;
2020-01-22 12:43:51 +01:00
if ( wasSetCurrentToTCP & & ! useUDP )
{
2019-02-05 12:41:00 +01:00
e . rtts . Reset ( ) ;
2020-01-22 12:43:51 +01:00
e . averageRTT = 0 ;
e . lastPingSeq = 0 ;
2019-02-05 12:41:00 +01:00
}
2018-11-09 16:44:01 +01:00
Endpoint tcpRelay ( e ) ;
2020-01-22 12:43:51 +01:00
tcpRelay . type = Endpoint : : Type : : TCP_RELAY ;
tcpRelay . averageRTT = 0 ;
tcpRelay . lastPingSeq = 0 ;
tcpRelay . lastPingTime = 0 ;
2018-11-09 16:44:01 +01:00
tcpRelay . rtts . Reset ( ) ;
2020-01-22 12:43:51 +01:00
tcpRelay . udpPongCount = 0 ;
tcpRelay . id = tcpRelay . id ^ ( ( int64_t ) ( FOURCC ( ' T ' , ' C ' , ' P ' , 0 ) ) < < 32 ) ;
if ( setCurrentEndpointToTCP & & endpoints . at ( currentEndpoint ) . type ! = Endpoint : : Type : : TCP_RELAY )
{
2019-02-05 12:41:00 +01:00
LOGV ( " Setting current endpoint to TCP " ) ;
2020-01-22 12:43:51 +01:00
setCurrentEndpointToTCP = false ;
currentEndpoint = tcpRelay . id ;
preferredRelay = tcpRelay . id ;
2018-07-17 18:48:21 +02:00
}
relays . push_back ( tcpRelay ) ;
}
2019-04-15 01:43:10 +02:00
MutexGuard m ( endpointsMutex ) ;
2020-01-22 12:43:51 +01:00
for ( Endpoint & e : relays )
{
endpoints [ e . id ] = e ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
didAddTcpRelays = true ;
2018-07-17 18:48:21 +02:00
}
}
2017-02-02 17:24:40 +01:00
2017-03-30 16:06:59 +02:00
# if defined(__APPLE__)
2020-01-22 12:43:51 +01:00
static void initMachTimestart ( )
{
mach_timebase_info_data_t tb = { 0 , 0 } ;
2018-06-04 21:37:43 +02:00
mach_timebase_info ( & tb ) ;
VoIPController : : machTimebase = tb . numer ;
VoIPController : : machTimebase / = tb . denom ;
VoIPController : : machTimestart = mach_absolute_time ( ) ;
2017-03-30 16:06:59 +02:00
}
# endif
2020-01-22 12:43:51 +01:00
double VoIPController : : GetCurrentTime ( )
{
2017-02-02 17:24:40 +01:00
# if defined(__linux__)
struct timespec ts ;
clock_gettime ( CLOCK_MONOTONIC , & ts ) ;
2020-01-22 12:43:51 +01:00
return ts . tv_sec + ( double ) ts . tv_nsec / 1000000000.0 ;
2017-02-02 17:24:40 +01:00
# elif defined(__APPLE__)
2018-06-04 21:37:43 +02:00
static pthread_once_t token = PTHREAD_ONCE_INIT ;
pthread_once ( & token , & initMachTimestart ) ;
2017-02-02 17:24:40 +01:00
return ( mach_absolute_time ( ) - machTimestart ) * machTimebase / 1000000000.0f ;
2017-04-17 20:57:07 +02:00
# elif defined(_WIN32)
2020-01-22 12:43:51 +01:00
if ( ! didInitWin32TimeScale )
{
2017-04-17 20:57:07 +02:00
LARGE_INTEGER scale ;
QueryPerformanceFrequency ( & scale ) ;
2020-01-22 12:43:51 +01:00
win32TimeScale = scale . QuadPart ;
didInitWin32TimeScale = true ;
2017-04-17 20:57:07 +02:00
}
LARGE_INTEGER t ;
QueryPerformanceCounter ( & t ) ;
2020-01-22 12:43:51 +01:00
return ( double ) t . QuadPart / ( double ) win32TimeScale ;
2017-02-02 17:24:40 +01:00
# endif
}
2020-01-22 12:43:51 +01:00
void VoIPController : : KDF ( unsigned char * msgKey , size_t x , unsigned char * aesKey , unsigned char * aesIv )
{
2017-02-02 17:24:40 +01:00
uint8_t sA [ SHA1_LENGTH ] , sB [ SHA1_LENGTH ] , sC [ SHA1_LENGTH ] , sD [ SHA1_LENGTH ] ;
2017-04-28 13:17:56 +02:00
BufferOutputStream buf ( 128 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + x , 32 ) ;
2017-03-30 16:06:59 +02:00
crypto . sha1 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sA ) ;
2017-02-02 17:24:40 +01:00
buf . Reset ( ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + 32 + x , 16 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + 48 + x , 16 ) ;
2017-03-30 16:06:59 +02:00
crypto . sha1 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sB ) ;
2017-02-02 17:24:40 +01:00
buf . Reset ( ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + 64 + x , 32 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
crypto . sha1 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sC ) ;
2017-02-02 17:24:40 +01:00
buf . Reset ( ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + 96 + x , 32 ) ;
2017-03-30 16:06:59 +02:00
crypto . sha1 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sD ) ;
2017-02-02 17:24:40 +01:00
buf . Reset ( ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( sA , 8 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( sB + 8 , 12 ) ;
buf . WriteBytes ( sC + 4 , 12 ) ;
assert ( buf . GetLength ( ) = = 32 ) ;
2017-02-02 17:24:40 +01:00
memcpy ( aesKey , buf . GetBuffer ( ) , 32 ) ;
buf . Reset ( ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( sA + 8 , 12 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( sB , 8 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( sC + 16 , 4 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( sD , 8 ) ;
2020-01-22 12:43:51 +01:00
assert ( buf . GetLength ( ) = = 32 ) ;
2017-02-02 17:24:40 +01:00
memcpy ( aesIv , buf . GetBuffer ( ) , 32 ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : KDF2 ( unsigned char * msgKey , size_t x , unsigned char * aesKey , unsigned char * aesIv )
{
2018-05-15 20:23:46 +02:00
uint8_t sA [ 32 ] , sB [ 32 ] ;
BufferOutputStream buf ( 128 ) ;
buf . WriteBytes ( msgKey , 16 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + x , 36 ) ;
2018-05-15 20:23:46 +02:00
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sA ) ;
buf . Reset ( ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( encryptionKey + 40 + x , 36 ) ;
2018-05-15 20:23:46 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sB ) ;
buf . Reset ( ) ;
buf . WriteBytes ( sA , 8 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( sB + 8 , 16 ) ;
buf . WriteBytes ( sA + 24 , 8 ) ;
2018-05-15 20:23:46 +02:00
memcpy ( aesKey , buf . GetBuffer ( ) , 32 ) ;
buf . Reset ( ) ;
buf . WriteBytes ( sB , 8 ) ;
2020-01-22 12:43:51 +01:00
buf . WriteBytes ( sA + 8 , 16 ) ;
buf . WriteBytes ( sB + 24 , 8 ) ;
2018-05-15 20:23:46 +02:00
memcpy ( aesIv , buf . GetBuffer ( ) , 32 ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendPublicEndpointsRequest ( const Endpoint & relay )
{
if ( ! useUDP )
2017-07-03 03:42:49 +02:00
return ;
2017-04-17 20:57:07 +02:00
LOGD ( " Sending public endpoints request to %s:%d " , relay . address . ToString ( ) . c_str ( ) , relay . port ) ;
2020-01-22 12:43:51 +01:00
publicEndpointsReqTime = GetCurrentTime ( ) ;
waitingForRelayPeerInfo = true ;
2019-04-15 01:43:10 +02:00
Buffer buf ( 32 ) ;
memcpy ( * buf , relay . peerTag , 16 ) ;
2020-01-22 12:43:51 +01:00
memset ( * buf + 16 , 0xFF , 16 ) ;
2019-04-15 01:43:10 +02:00
udpSocket - > Send ( NetworkPacket {
std : : move ( buf ) ,
relay . address ,
relay . port ,
2020-01-22 12:43:51 +01:00
NetworkProtocol : : UDP } ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
Endpoint & VoIPController : : GetEndpointByType ( int type )
{
if ( type = = Endpoint : : Type : : UDP_RELAY & & preferredRelay )
2018-11-09 16:44:01 +01:00
return endpoints . at ( preferredRelay ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
if ( e . second . type = = type )
2018-11-09 16:44:01 +01:00
return e . second ;
2017-02-02 17:24:40 +01:00
}
2018-11-09 16:44:01 +01:00
throw out_of_range ( " no endpoint " ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendPacketReliably ( unsigned char type , unsigned char * data , size_t len , double retryInterval , double timeout )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2017-04-19 15:39:27 +02:00
LOGD ( " Send reliably, type=%u, len=%u, retry=%.3f, timeout=%.3f " , type , unsigned ( len ) , retryInterval , timeout ) ;
2018-06-04 21:37:43 +02:00
QueuedPacket pkt ;
2020-01-22 12:43:51 +01:00
if ( data )
{
2018-06-04 21:37:43 +02:00
Buffer b ( len ) ;
b . CopyFrom ( data , 0 , len ) ;
2020-01-22 12:43:51 +01:00
pkt . data = move ( b ) ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
pkt . type = type ;
pkt . retryInterval = retryInterval ;
pkt . timeout = timeout ;
pkt . firstSentTime = 0 ;
pkt . lastSentTime = 0 ;
2019-04-15 01:43:10 +02:00
queuedPackets . push_back ( move ( pkt ) ) ;
2018-11-18 00:36:55 +01:00
messageThread . Post ( std : : bind ( & VoIPController : : UpdateQueuedPackets , this ) ) ;
2020-01-22 12:43:51 +01:00
if ( timeout > 0.0 )
{
2018-11-18 00:36:55 +01:00
messageThread . Post ( std : : bind ( & VoIPController : : UpdateQueuedPackets , this ) , timeout ) ;
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendExtra ( Buffer & data , unsigned char type )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2019-04-24 18:36:32 +02:00
LOGV ( " Sending extra type %u length %u " , type , ( unsigned int ) data . Length ( ) ) ;
2020-01-22 12:43:51 +01:00
for ( vector < UnacknowledgedExtraData > : : iterator x = currentExtras . begin ( ) ; x ! = currentExtras . end ( ) ; + + x )
{
if ( x - > type = = type )
{
x - > firstContainingSeq = 0 ;
x - > data = move ( data ) ;
2018-11-18 00:36:55 +01:00
return ;
}
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
UnacknowledgedExtraData xd = { type , move ( data ) , 0 } ;
2018-11-18 00:36:55 +01:00
currentExtras . push_back ( move ( xd ) ) ;
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : DebugCtl ( int request , int param )
{
2017-02-02 17:24:40 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendUdpPing ( Endpoint & endpoint )
{
if ( endpoint . type ! = Endpoint : : Type : : UDP_RELAY )
2017-07-03 03:42:49 +02:00
return ;
BufferOutputStream p ( 1024 ) ;
2018-11-09 16:44:01 +01:00
p . WriteBytes ( endpoint . peerTag , 16 ) ;
2017-07-03 03:42:49 +02:00
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 2 ) ;
2018-11-09 16:44:01 +01:00
int64_t id ;
2020-01-22 12:43:51 +01:00
crypto . rand_bytes ( reinterpret_cast < uint8_t * > ( & id ) , 8 ) ;
2018-11-09 16:44:01 +01:00
p . WriteInt64 ( id ) ;
2020-01-22 12:43:51 +01:00
endpoint . udpPingTimes [ id ] = GetCurrentTime ( ) ;
2019-04-15 01:43:10 +02:00
udpSocket - > Send ( NetworkPacket {
Buffer ( std : : move ( p ) ) ,
endpoint . GetAddress ( ) ,
endpoint . port ,
2020-01-22 12:43:51 +01:00
NetworkProtocol : : UDP } ) ;
2019-04-15 01:43:10 +02:00
endpoint . totalUdpPings + + ;
2018-11-09 16:44:01 +01:00
LOGV ( " Sending UDP ping to %s:%d, id % " PRId64 , endpoint . GetAddress ( ) . ToString ( ) . c_str ( ) , endpoint . port , id ) ;
2017-07-03 03:42:49 +02:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ResetUdpAvailability ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2018-07-29 20:21:34 +02:00
LOGI ( " Resetting UDP availability " ) ;
2020-01-22 12:43:51 +01:00
if ( udpPingTimeoutID ! = MessageThread : : INVALID_ID )
{
2018-07-29 20:21:34 +02:00
messageThread . Cancel ( udpPingTimeoutID ) ;
}
{
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
e . second . udpPongCount = 0 ;
2019-04-15 01:43:10 +02:00
e . second . udpPingTimes . clear ( ) ;
2018-07-29 20:21:34 +02:00
}
}
2020-01-22 12:43:51 +01:00
udpPingCount = 0 ;
udpConnectivityState = UDP_PING_PENDING ;
udpPingTimeoutID = messageThread . Post ( std : : bind ( & VoIPController : : SendUdpPings , this ) , 0.0 , 0.5 ) ;
2018-07-29 20:21:34 +02:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ResetEndpointPingStats ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
e . second . averageRTT = 0.0 ;
2018-11-09 16:44:01 +01:00
e . second . rtts . Reset ( ) ;
2018-08-24 01:29:07 +02:00
}
}
2018-11-18 00:36:55 +01:00
# pragma mark - Video
2018-11-09 16:44:01 +01:00
2020-01-22 12:43:51 +01:00
void VoIPController : : SetVideoSource ( video : : VideoSource * source )
{
shared_ptr < Stream > stm = GetStreamByType ( STREAM_TYPE_VIDEO , true ) ;
if ( ! stm )
{
2019-03-10 23:12:09 +01:00
LOGE ( " Can't set video source when there is no outgoing video stream " ) ;
return ;
}
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
if ( source )
{
if ( ! stm - > enabled )
{
stm - > enabled = true ;
messageThread . Post ( [ this , stm ] { SendStreamFlags ( * stm ) ; } ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( ! videoPacketSender )
videoPacketSender = new video : : VideoPacketSender ( this , source , stm ) ;
2019-04-15 01:43:10 +02:00
else
videoPacketSender - > SetSource ( source ) ;
2020-01-22 12:43:51 +01:00
}
else
{
if ( stm - > enabled )
{
stm - > enabled = false ;
messageThread . Post ( [ this , stm ] { SendStreamFlags ( * stm ) ; } ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( videoPacketSender )
{
2019-04-15 01:43:10 +02:00
videoPacketSender - > SetSource ( NULL ) ;
2019-02-05 12:41:00 +01:00
}
}
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetVideoRenderer ( video : : VideoRenderer * renderer )
{
videoRenderer = renderer ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetVideoCodecSpecificData ( const std : : vector < Buffer > & data )
{
2018-11-09 16:44:01 +01:00
outgoingStreams [ 1 ] - > codecSpecificData . clear ( ) ;
2020-01-22 12:43:51 +01:00
for ( const Buffer & csd : data )
{
2018-11-09 16:44:01 +01:00
outgoingStreams [ 1 ] - > codecSpecificData . push_back ( Buffer : : CopyOf ( csd ) ) ;
}
LOGI ( " Set outgoing video stream CSD " ) ;
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendVideoFrame ( const Buffer & frame , uint32_t flags , uint32_t rotation )
{
2019-03-10 23:12:09 +01:00
//LOGI("Send video frame %u flags %u", (unsigned int)frame.Length(), flags);
2020-01-22 12:43:51 +01:00
shared_ptr < Stream > stm = GetStreamByType ( STREAM_TYPE_VIDEO , true ) ;
if ( stm )
{
2018-11-09 16:44:01 +01:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : ProcessIncomingVideoFrame ( Buffer frame , uint32_t pts , bool keyframe , uint16_t rotation )
{
2018-11-09 16:44:01 +01:00
//LOGI("Incoming video frame size %u pts %u", (unsigned int)frame.Length(), pts);
2020-01-22 12:43:51 +01:00
if ( frame . Length ( ) = = 0 )
{
2018-11-09 16:44:01 +01:00
LOGE ( " EMPTY FRAME " ) ;
}
2020-01-22 12:43:51 +01:00
if ( videoRenderer )
{
shared_ptr < Stream > stm = GetStreamByType ( STREAM_TYPE_VIDEO , false ) ;
size_t offset = 0 ;
if ( keyframe )
{
2019-04-15 01:43:10 +02:00
BufferInputStream in ( frame ) ;
2020-01-22 12:43:51 +01:00
uint16_t width = ( uint16_t ) in . ReadInt16 ( ) ;
uint16_t height = ( uint16_t ) in . ReadInt16 ( ) ;
uint8_t sizeAndFlag = in . ReadByte ( ) ;
int size = sizeAndFlag & 0x0F ;
bool reset = ( sizeAndFlag & 0x80 ) = = 0x80 ;
if ( reset | | ! stm - > csdIsValid | | stm - > width ! = width | | stm - > height ! = height )
{
stm - > width = width ;
stm - > height = height ;
2019-04-15 01:43:10 +02:00
stm - > codecSpecificData . clear ( ) ;
2020-01-22 12:43:51 +01:00
for ( int i = 0 ; i < size ; i + + )
{
size_t len = in . ReadByte ( ) ;
2019-04-15 01:43:10 +02:00
Buffer b ( len ) ;
in . ReadBytes ( b ) ;
stm - > codecSpecificData . push_back ( move ( b ) ) ;
}
2020-01-22 12:43:51 +01:00
stm - > csdIsValid = false ;
}
else
{
for ( int i = 0 ; i < size ; i + + )
{
size_t len = in . ReadByte ( ) ;
in . Seek ( in . GetOffset ( ) + len ) ;
2019-04-15 01:43:10 +02:00
}
}
2020-01-22 12:43:51 +01:00
offset = in . GetOffset ( ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( ! stm - > csdIsValid & & stm - > width & & stm - > height )
{
2019-02-05 12:41:00 +01:00
videoRenderer - > Reset ( stm - > codec , stm - > width , stm - > height , stm - > codecSpecificData ) ;
2020-01-22 12:43:51 +01:00
stm - > csdIsValid = true ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
if ( lastReceivedVideoFrameNumber = = UINT32_MAX | | lastReceivedVideoFrameNumber = = pts - 1 | | keyframe )
{
lastReceivedVideoFrameNumber = pts ;
2019-02-05 12:41:00 +01:00
//LOGV("3 before decode %u", (unsigned int)frame.Length());
2020-01-22 12:43:51 +01:00
if ( stm - > rotation ! = rotation )
{
stm - > rotation = rotation ;
2019-04-15 01:43:10 +02:00
videoRenderer - > SetRotation ( rotation ) ;
}
2020-01-22 12:43:51 +01:00
if ( offset = = 0 )
{
2019-04-15 01:43:10 +02:00
videoRenderer - > DecodeAndDisplay ( move ( frame ) , pts ) ;
}
2020-01-22 12:43:51 +01:00
else
{
videoRenderer - > DecodeAndDisplay ( Buffer : : CopyOf ( frame , offset , frame . Length ( ) - offset ) , pts ) ;
}
}
else
{
2019-02-05 12:41:00 +01:00
LOGW ( " Skipping non-keyframe after packet loss... " ) ;
}
2018-11-09 16:44:01 +01:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SetupOutgoingVideoStream ( )
{
vector < uint32_t > myEncoders = video : : VideoSource : : GetAvailableEncoders ( ) ;
shared_ptr < Stream > vstm = make_shared < Stream > ( ) ;
vstm - > id = 2 ;
vstm - > type = STREAM_TYPE_VIDEO ;
2019-02-05 12:41:00 +01:00
2020-01-22 12:43:51 +01:00
if ( find ( myEncoders . begin ( ) , myEncoders . end ( ) , CODEC_HEVC ) ! = myEncoders . end ( ) & & find ( peerVideoDecoders . begin ( ) , peerVideoDecoders . end ( ) , CODEC_HEVC ) ! = peerVideoDecoders . end ( ) )
{
vstm - > codec = CODEC_HEVC ;
}
else if ( find ( myEncoders . begin ( ) , myEncoders . end ( ) , CODEC_AVC ) ! = myEncoders . end ( ) & & find ( peerVideoDecoders . begin ( ) , peerVideoDecoders . end ( ) , CODEC_AVC ) ! = peerVideoDecoders . end ( ) )
{
vstm - > codec = CODEC_AVC ;
}
else if ( find ( myEncoders . begin ( ) , myEncoders . end ( ) , CODEC_VP8 ) ! = myEncoders . end ( ) & & find ( peerVideoDecoders . begin ( ) , peerVideoDecoders . end ( ) , CODEC_VP8 ) ! = peerVideoDecoders . end ( ) )
{
vstm - > codec = CODEC_VP8 ;
}
else
{
2019-02-05 12:41:00 +01:00
LOGW ( " Can't setup outgoing video stream: no codecs in common " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
vstm - > enabled = false ;
2019-02-05 12:41:00 +01:00
outgoingStreams . push_back ( vstm ) ;
}
2018-07-17 18:48:21 +02:00
# pragma mark - Timer methods
2020-01-22 12:43:51 +01:00
void VoIPController : : SendUdpPings ( )
{
2019-02-07 14:14:24 +01:00
LOGW ( " Send udp pings " ) ;
2020-01-22 12:43:51 +01:00
ENFORCE_MSG_THREAD ;
2019-04-15 01:43:10 +02:00
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
if ( e . second . type = = Endpoint : : Type : : UDP_RELAY )
{
2018-11-09 16:44:01 +01:00
SendUdpPing ( e . second ) ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( udpConnectivityState = = UDP_UNKNOWN | | udpConnectivityState = = UDP_PING_PENDING )
udpConnectivityState = UDP_PING_SENT ;
2018-07-17 18:48:21 +02:00
udpPingCount + + ;
2020-01-22 12:43:51 +01:00
if ( udpPingCount = = 4 | | udpPingCount = = 10 )
{
2018-07-17 18:48:21 +02:00
messageThread . CancelSelf ( ) ;
2020-01-22 12:43:51 +01:00
udpPingTimeoutID = messageThread . Post ( std : : bind ( & VoIPController : : EvaluateUdpPingResults , this ) , 1.0 ) ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : EvaluateUdpPingResults ( )
{
double avgPongs = 0 ;
int count = 0 ;
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
if ( e . type = = Endpoint : : Type : : UDP_RELAY )
{
if ( e . udpPongCount > 0 )
{
avgPongs + = ( double ) e . udpPongCount ;
2018-07-17 18:48:21 +02:00
count + + ;
}
}
}
2020-01-22 12:43:51 +01:00
if ( count > 0 )
avgPongs / = ( double ) count ;
2018-07-17 18:48:21 +02:00
else
2020-01-22 12:43:51 +01:00
avgPongs = 0.0 ;
2018-07-17 18:48:21 +02:00
LOGI ( " UDP ping reply count: %.2f " , avgPongs ) ;
2020-01-22 12:43:51 +01:00
if ( avgPongs = = 0.0 & & proxyProtocol = = PROXY_SOCKS5 & & udpSocket ! = realUdpSocket )
{
2018-12-19 17:51:45 +01:00
LOGI ( " Proxy does not let UDP through, closing proxy connection and using UDP directly " ) ;
2020-01-22 12:43:51 +01:00
NetworkSocket * proxySocket = udpSocket ;
2018-12-19 17:51:45 +01:00
proxySocket - > Close ( ) ;
2020-01-22 12:43:51 +01:00
udpSocket = realUdpSocket ;
2018-12-19 17:51:45 +01:00
selectCanceller - > CancelSelect ( ) ;
delete proxySocket ;
2020-01-22 12:43:51 +01:00
proxySupportsUDP = false ;
2018-12-19 17:51:45 +01:00
ResetUdpAvailability ( ) ;
return ;
}
2020-01-22 12:43:51 +01:00
bool configUseTCP = ServerConfig : : GetSharedInstance ( ) - > GetBoolean ( " use_tcp " , true ) ;
if ( configUseTCP )
{
if ( avgPongs = = 0.0 | | ( udpConnectivityState = = UDP_BAD & & avgPongs < 7.0 ) )
{
if ( needRateFlags & NEED_RATE_FLAG_UDP_NA )
needRate = true ;
udpConnectivityState = UDP_NOT_AVAILABLE ;
useTCP = true ;
useUDP = avgPongs > 1.0 ;
if ( endpoints . at ( currentEndpoint ) . type ! = Endpoint : : Type : : TCP_RELAY )
setCurrentEndpointToTCP = true ;
2019-02-05 12:41:00 +01:00
AddTCPRelays ( ) ;
2020-01-22 12:43:51 +01:00
waitingForRelayPeerInfo = false ;
}
else if ( avgPongs < 3.0 )
{
if ( needRateFlags & NEED_RATE_FLAG_UDP_BAD )
needRate = true ;
udpConnectivityState = UDP_BAD ;
useTCP = true ;
setCurrentEndpointToTCP = true ;
2019-02-05 12:41:00 +01:00
AddTCPRelays ( ) ;
2020-01-22 12:43:51 +01:00
udpPingTimeoutID = messageThread . Post ( std : : bind ( & VoIPController : : SendUdpPings , this ) , 0.5 , 0.5 ) ;
}
else
{
udpPingTimeoutID = MessageThread : : INVALID_ID ;
udpConnectivityState = UDP_AVAILABLE ;
}
}
else
{
udpPingTimeoutID = MessageThread : : INVALID_ID ;
udpConnectivityState = UDP_NOT_AVAILABLE ;
}
}
void VoIPController : : SendRelayPings ( )
{
ENFORCE_MSG_THREAD ;
if ( ( state = = STATE_ESTABLISHED | | state = = STATE_RECONNECTING ) & & endpoints . size ( ) > 1 )
{
Endpoint * _preferredRelay = & endpoints . at ( preferredRelay ) ;
Endpoint * _currentEndpoint = & endpoints . at ( currentEndpoint ) ;
Endpoint * minPingRelay = _preferredRelay ;
double minPing = _preferredRelay - > averageRTT * ( _preferredRelay - > type = = Endpoint : : Type : : TCP_RELAY ? 2 : 1 ) ;
if ( minPing = = 0.0 ) // force the switch to an available relay, if any
minPing = DBL_MAX ;
for ( pair < const int64_t , Endpoint > & _endpoint : endpoints )
{
Endpoint & endpoint = _endpoint . second ;
if ( endpoint . type = = Endpoint : : Type : : TCP_RELAY & & ! useTCP )
2018-07-17 18:48:21 +02:00
continue ;
2020-01-22 12:43:51 +01:00
if ( endpoint . type = = Endpoint : : Type : : UDP_RELAY & & ! useUDP )
2019-02-05 12:41:00 +01:00
continue ;
2020-01-22 12:43:51 +01:00
if ( GetCurrentTime ( ) - endpoint . lastPingTime > = 10 )
{
2018-11-09 16:44:01 +01:00
LOGV ( " Sending ping to %s " , endpoint . GetAddress ( ) . ToString ( ) . c_str ( ) ) ;
SendOrEnqueuePacket ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ ( endpoint . lastPingSeq = GenerateOutSeq ( ) ) ,
/*.type=*/ PKT_PING ,
/*.len=*/ 0 ,
/*.data=*/ Buffer ( ) ,
/*.endpoint=*/ endpoint . id } ) ;
endpoint . lastPingTime = GetCurrentTime ( ) ;
}
if ( ( useUDP & & endpoint . type = = Endpoint : : Type : : UDP_RELAY ) | | ( useTCP & & endpoint . type = = Endpoint : : Type : : TCP_RELAY ) )
{
double k = endpoint . type = = Endpoint : : Type : : UDP_RELAY ? 1 : 2 ;
if ( endpoint . averageRTT > 0 & & endpoint . averageRTT * k < minPing * relaySwitchThreshold )
{
minPing = endpoint . averageRTT * k ;
minPingRelay = & endpoint ;
2018-07-17 18:48:21 +02:00
}
}
}
2020-01-22 12:43:51 +01:00
if ( minPingRelay - > id ! = preferredRelay )
{
preferredRelay = minPingRelay - > id ;
_preferredRelay = minPingRelay ;
2018-11-09 16:44:01 +01:00
LOGV ( " set preferred relay to %s " , _preferredRelay - > address . ToString ( ) . c_str ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( _currentEndpoint - > type = = Endpoint : : Type : : UDP_RELAY | | _currentEndpoint - > type = = Endpoint : : Type : : TCP_RELAY )
{
currentEndpoint = preferredRelay ;
_currentEndpoint = _preferredRelay ;
2018-11-09 16:44:01 +01:00
}
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
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 ;
if ( endpoints . find ( p2pID ) ! = endpoints . end ( ) )
{
Endpoint & p2p = endpoints [ p2pID ] ;
if ( endpoints . find ( lanID ) ! = endpoints . end ( ) & & endpoints [ lanID ] . averageRTT > 0 & & endpoints [ lanID ] . averageRTT < minPing * relayToP2pSwitchThreshold )
{
currentEndpoint = lanID ;
2018-07-17 18:48:21 +02:00
LOGI ( " Switching to p2p (LAN) " ) ;
2020-01-22 12:43:51 +01:00
}
else
{
if ( p2p . averageRTT > 0 & & p2p . averageRTT < minPing * relayToP2pSwitchThreshold )
{
currentEndpoint = p2pID ;
2018-07-17 18:48:21 +02:00
LOGI ( " Switching to p2p (Inet) " ) ;
}
}
}
2020-01-22 12:43:51 +01:00
}
else
{
if ( minPing > 0 & & minPing < _currentEndpoint - > averageRTT * p2pToRelaySwitchThreshold )
{
2018-07-17 18:48:21 +02:00
LOGI ( " Switching to relay " ) ;
2020-01-22 12:43:51 +01:00
currentEndpoint = preferredRelay ;
2018-07-17 18:48:21 +02:00
}
}
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateRTT ( )
{
2018-07-17 18:48:21 +02:00
rttHistory . Add ( GetAverageRTT ( ) ) ;
//double v=rttHistory.Average();
2020-01-22 12:43:51 +01:00
if ( rttHistory [ 0 ] > 10.0 & & rttHistory [ 8 ] > 10.0 & & ( networkType = = NET_TYPE_EDGE | | networkType = = NET_TYPE_GPRS ) )
{
waitingForAcks = true ;
}
else
{
waitingForAcks = false ;
2018-07-17 18:48:21 +02:00
}
//LOGI("%.3lf/%.3lf, rtt diff %.3lf, waiting=%d, queue=%d", rttHistory[0], rttHistory[8], v, waitingForAcks, sendQueue->Size());
2020-01-22 12:43:51 +01:00
for ( vector < shared_ptr < Stream > > : : iterator stm = incomingStreams . begin ( ) ; stm ! = incomingStreams . end ( ) ; + + stm )
{
if ( ( * stm ) - > jitterBuffer )
{
int lostCount = ( * stm ) - > jitterBuffer - > GetAndResetLostPacketCount ( ) ;
if ( lostCount > 0 | | ( lostCount < 0 & & recvLossCount > ( ( uint32_t ) - lostCount ) ) )
recvLossCount + = lostCount ;
2018-07-17 18:48:21 +02:00
}
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateCongestion ( )
{
if ( conctl & & encoder )
{
uint32_t sendLossCount = conctl - > GetSendLossCount ( ) ;
sendLossCountHistory . Add ( sendLossCount - prevSendLossCount ) ;
prevSendLossCount = sendLossCount ;
double packetsPerSec = 1000 / ( double ) outgoingStreams [ 0 ] - > frameDuration ;
double avgSendLossCount = sendLossCountHistory . Average ( ) / packetsPerSec ;
2018-11-09 16:44:01 +01:00
//LOGV("avg send loss: %.3f%%", avgSendLossCount*100);
2018-07-17 18:48:21 +02:00
2020-01-22 12:43:51 +01:00
if ( avgSendLossCount > packetLossToEnableExtraEC & & networkType ! = NET_TYPE_GPRS & & networkType ! = NET_TYPE_EDGE )
{
if ( ! shittyInternetMode )
{
2018-07-17 18:48:21 +02:00
// Shitty Internet Mode™. Redundant redundancy you can trust.
2020-01-22 12:43:51 +01:00
shittyInternetMode = true ;
for ( shared_ptr < Stream > & s : outgoingStreams )
{
if ( s - > type = = STREAM_TYPE_AUDIO )
{
s - > extraECEnabled = true ;
2018-07-17 18:48:21 +02:00
SendStreamFlags ( * s ) ;
break ;
}
}
2020-01-22 12:43:51 +01:00
if ( encoder )
2018-07-17 18:48:21 +02:00
encoder - > SetSecondaryEncoderEnabled ( true ) ;
LOGW ( " Enabling extra EC " ) ;
2020-01-22 12:43:51 +01:00
if ( needRateFlags & NEED_RATE_FLAG_SHITTY_INTERNET_MODE )
needRate = true ;
wasExtraEC = true ;
}
}
if ( avgSendLossCount > 0.08 )
{
extraEcLevel = 4 ;
}
else if ( avgSendLossCount > 0.05 )
{
extraEcLevel = 3 ;
}
else if ( avgSendLossCount > 0.02 )
{
extraEcLevel = 2 ;
}
else
{
extraEcLevel = 0 ;
}
encoder - > SetPacketLoss ( ( int ) ( avgSendLossCount * 100.0 ) ) ;
if ( avgSendLossCount > rateMaxAcceptableSendLoss )
needRate = true ;
if ( ( avgSendLossCount < packetLossToEnableExtraEC | | networkType = = NET_TYPE_EDGE | | networkType = = NET_TYPE_GPRS ) & & shittyInternetMode )
{
shittyInternetMode = false ;
for ( shared_ptr < Stream > & s : outgoingStreams )
{
if ( s - > type = = STREAM_TYPE_AUDIO )
{
s - > extraECEnabled = false ;
2018-07-17 18:48:21 +02:00
SendStreamFlags ( * s ) ;
break ;
}
}
2020-01-22 12:43:51 +01:00
if ( encoder )
2018-07-17 18:48:21 +02:00
encoder - > SetSecondaryEncoderEnabled ( false ) ;
LOGW ( " Disabling extra EC " ) ;
}
2020-01-22 12:43:51 +01:00
if ( ! wasEncoderLaggy & & encoder - > GetComplexity ( ) < 10 )
wasEncoderLaggy = true ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateAudioBitrate ( )
{
if ( encoder & & conctl )
{
double time = GetCurrentTime ( ) ;
if ( ( audioInput & & ! audioInput - > IsInitialized ( ) ) | | ( audioOutput & & ! audioOutput - > IsInitialized ( ) ) )
{
2018-07-17 18:48:21 +02:00
LOGE ( " Audio I/O failed " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_AUDIO_IO ;
2018-07-17 18:48:21 +02:00
SetState ( STATE_FAILED ) ;
}
2020-01-22 12:43:51 +01:00
int act = conctl - > GetBandwidthControlAction ( ) ;
if ( shittyInternetMode )
{
2018-07-17 18:48:21 +02:00
encoder - > SetBitrate ( 8000 ) ;
2020-01-22 12:43:51 +01:00
}
else if ( act = = TGVOIP_CONCTL_ACT_DECREASE )
{
uint32_t bitrate = encoder - > GetBitrate ( ) ;
if ( bitrate > 8000 )
encoder - > SetBitrate ( bitrate < ( minAudioBitrate + audioBitrateStepDecr ) ? minAudioBitrate : ( bitrate - audioBitrateStepDecr ) ) ;
}
else if ( act = = TGVOIP_CONCTL_ACT_INCREASE )
{
uint32_t bitrate = encoder - > GetBitrate ( ) ;
if ( bitrate < maxBitrate )
encoder - > SetBitrate ( bitrate + audioBitrateStepIncr ) ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
if ( state = = STATE_ESTABLISHED & & time - lastRecvPacketTime > = reconnectingTimeout )
{
2018-07-17 18:48:21 +02:00
SetState ( STATE_RECONNECTING ) ;
2020-01-22 12:43:51 +01:00
if ( needRateFlags & NEED_RATE_FLAG_RECONNECTING )
needRate = true ;
wasReconnecting = true ;
2018-07-29 20:21:34 +02:00
ResetUdpAvailability ( ) ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
if ( state = = STATE_ESTABLISHED | | state = = STATE_RECONNECTING )
{
if ( time - lastRecvPacketTime > = config . recvTimeout )
{
const Endpoint & _currentEndpoint = endpoints . at ( currentEndpoint ) ;
if ( _currentEndpoint . type ! = Endpoint : : Type : : UDP_RELAY & & _currentEndpoint . type ! = Endpoint : : Type : : TCP_RELAY )
{
2018-07-17 18:48:21 +02:00
LOGW ( " Packet receive timeout, switching to relay " ) ;
2020-01-22 12:43:51 +01:00
currentEndpoint = preferredRelay ;
for ( pair < const int64_t , Endpoint > & _e : endpoints )
{
Endpoint & e = _e . second ;
if ( e . type = = Endpoint : : Type : : UDP_P2P_INET | | e . type = = Endpoint : : Type : : UDP_P2P_LAN )
{
e . averageRTT = 0 ;
2018-11-09 16:44:01 +01:00
e . rtts . Reset ( ) ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
if ( allowP2p )
{
2018-07-17 18:48:21 +02:00
SendPublicEndpointsRequest ( ) ;
}
UpdateDataSavingState ( ) ;
UpdateAudioBitrateLimit ( ) ;
BufferOutputStream s ( 4 ) ;
s . WriteInt32 ( dataSavingMode ? INIT_FLAG_DATA_SAVING_ENABLED : 0 ) ;
2020-01-22 12:43:51 +01:00
if ( peerVersion < 6 )
{
2018-07-17 18:48:21 +02:00
SendPacketReliably ( PKT_NETWORK_CHANGED , s . GetBuffer ( ) , s . GetLength ( ) , 1 , 20 ) ;
2020-01-22 12:43:51 +01:00
}
else
{
2018-07-17 18:48:21 +02:00
Buffer buf ( move ( s ) ) ;
SendExtra ( buf , EXTRA_TYPE_NETWORK_CHANGED ) ;
}
2020-01-22 12:43:51 +01:00
lastRecvPacketTime = time ;
}
else
{
2018-07-17 18:48:21 +02:00
LOGW ( " Packet receive timeout, disconnecting " ) ;
2020-01-22 12:43:51 +01:00
lastError = ERROR_TIMEOUT ;
2018-07-17 18:48:21 +02:00
SetState ( STATE_FAILED ) ;
}
}
}
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateSignalBars ( )
{
int prevSignalBarCount = GetSignalBarsCount ( ) ;
double packetsPerSec = 1000 / ( double ) outgoingStreams [ 0 ] - > frameDuration ;
double avgSendLossCount = sendLossCountHistory . Average ( ) / packetsPerSec ;
2018-07-17 18:48:21 +02:00
2020-01-22 12:43:51 +01:00
int signalBarCount = 4 ;
if ( state = = STATE_RECONNECTING | | waitingForAcks )
signalBarCount = 1 ;
if ( endpoints . at ( currentEndpoint ) . type = = Endpoint : : Type : : TCP_RELAY )
{
signalBarCount = std : : min ( signalBarCount , 3 ) ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
if ( avgSendLossCount > 0.1 )
{
signalBarCount = 1 ;
}
else if ( avgSendLossCount > 0.0625 )
{
signalBarCount = std : : min ( signalBarCount , 2 ) ;
}
else if ( avgSendLossCount > 0.025 )
{
signalBarCount = std : : min ( signalBarCount , 3 ) ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & stm : incomingStreams )
{
if ( stm - > jitterBuffer )
{
2018-07-17 18:48:21 +02:00
double avgLateCount [ 3 ] ;
stm - > jitterBuffer - > GetAverageLateCount ( avgLateCount ) ;
2020-01-22 12:43:51 +01:00
if ( avgLateCount [ 2 ] > = 0.2 )
signalBarCount = 1 ;
else if ( avgLateCount [ 2 ] > = 0.1 )
signalBarCount = std : : min ( signalBarCount , 2 ) ;
2018-07-17 18:48:21 +02:00
}
}
signalBarsHistory . Add ( static_cast < unsigned char > ( signalBarCount ) ) ;
//LOGV("Signal bar count history %08X", *reinterpret_cast<uint32_t *>(&signalBarsHistory));
2020-01-22 12:43:51 +01:00
int _signalBarCount = GetSignalBarsCount ( ) ;
if ( _signalBarCount ! = prevSignalBarCount )
{
2018-07-17 18:48:21 +02:00
LOGD ( " SIGNAL BAR COUNT CHANGED: %d " , _signalBarCount ) ;
2020-01-22 12:43:51 +01:00
if ( callbacks . signalBarCountChanged )
2018-07-17 18:48:21 +02:00
callbacks . signalBarCountChanged ( this , _signalBarCount ) ;
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : UpdateQueuedPackets ( )
{
2018-11-21 01:38:26 +01:00
vector < PendingOutgoingPacket > packetsToSend ;
2020-01-22 12:43:51 +01:00
for ( std : : vector < QueuedPacket > : : iterator qp = queuedPackets . begin ( ) ; qp ! = queuedPackets . end ( ) ; )
{
if ( qp - > timeout > 0 & & qp - > firstSentTime > 0 & & GetCurrentTime ( ) - qp - > firstSentTime > = qp - > timeout )
{
2019-04-15 01:43:10 +02:00
LOGD ( " Removing queued packet because of timeout " ) ;
2020-01-22 12:43:51 +01:00
qp = queuedPackets . erase ( qp ) ;
2019-04-15 01:43:10 +02:00
continue ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
if ( GetCurrentTime ( ) - qp - > lastSentTime > = qp - > retryInterval )
{
2019-04-15 01:43:10 +02:00
messageThread . Post ( std : : bind ( & VoIPController : : UpdateQueuedPackets , this ) , qp - > retryInterval ) ;
2020-01-22 12:43:51 +01:00
uint32_t seq = GenerateOutSeq ( ) ;
2019-04-15 01:43:10 +02:00
qp - > seqs . Add ( seq ) ;
2020-01-22 12:43:51 +01:00
qp - > lastSentTime = GetCurrentTime ( ) ;
2019-04-15 01:43:10 +02:00
//LOGD("Sending queued packet, seq=%u, type=%u, len=%u", seq, qp.type, qp.data.Length());
Buffer buf ( qp - > data . Length ( ) ) ;
2020-01-22 12:43:51 +01:00
if ( qp - > firstSentTime = = 0 )
qp - > firstSentTime = qp - > lastSentTime ;
if ( qp - > data . Length ( ) )
2019-04-15 01:43:10 +02:00
buf . CopyFrom ( qp - > data , qp - > data . Length ( ) ) ;
packetsToSend . push_back ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ seq ,
/*.type=*/ qp - > type ,
/*.len=*/ qp - > data . Length ( ) ,
/*.data=*/ move ( buf ) ,
/*.endpoint=*/ 0 } ) ;
2019-04-15 01:43:10 +02:00
}
+ + qp ;
2018-11-21 01:38:26 +01:00
}
2020-01-22 12:43:51 +01:00
for ( PendingOutgoingPacket & pkt : packetsToSend )
{
2018-11-21 01:38:26 +01:00
SendOrEnqueuePacket ( move ( pkt ) ) ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendNopPacket ( )
{
if ( state ! = STATE_ESTABLISHED )
2018-12-12 01:28:11 +01:00
return ;
2018-11-09 16:44:01 +01:00
SendOrEnqueuePacket ( PendingOutgoingPacket {
2020-01-22 12:43:51 +01:00
/*.seq=*/ ( firstSentPing = GenerateOutSeq ( ) ) ,
/*.type=*/ PKT_NOP ,
/*.len=*/ 0 ,
/*.data=*/ Buffer ( ) ,
/*.endpoint=*/ 0 } ) ;
2018-07-17 18:48:21 +02:00
}
2020-01-22 12:43:51 +01:00
void VoIPController : : SendPublicEndpointsRequest ( )
{
2019-04-15 01:43:10 +02:00
ENFORCE_MSG_THREAD ;
2020-01-22 12:43:51 +01:00
if ( ! allowP2p )
2018-07-17 18:48:21 +02:00
return ;
LOGI ( " Sending public endpoints request " ) ;
2020-01-22 12:43:51 +01:00
for ( pair < const int64_t , Endpoint > & e : endpoints )
{
if ( e . second . type = = Endpoint : : Type : : UDP_RELAY & & ! e . second . IsIPv6Only ( ) )
{
2018-11-09 16:44:01 +01:00
SendPublicEndpointsRequest ( e . second ) ;
2018-07-17 18:48:21 +02:00
}
}
publicEndpointsReqCount + + ;
2020-01-22 12:43:51 +01:00
if ( publicEndpointsReqCount < 10 )
{
messageThread . Post ( [ this ] {
if ( waitingForRelayPeerInfo )
{
2018-07-17 18:48:21 +02:00
LOGW ( " Resending peer relay info request " ) ;
SendPublicEndpointsRequest ( ) ;
}
2020-01-22 12:43:51 +01:00
} ,
5.0 ) ;
}
else
{
publicEndpointsReqCount = 0 ;
2018-07-17 18:48:21 +02:00
}
}
2020-01-22 12:43:51 +01:00
void VoIPController : : TickJitterBufferAndCongestionControl ( )
{
2018-07-17 18:48:21 +02:00
// TODO get rid of this and update states of these things internally and retroactively
2020-01-22 12:43:51 +01:00
for ( shared_ptr < Stream > & stm : incomingStreams )
{
if ( stm - > jitterBuffer )
{
2018-07-17 18:48:21 +02:00
stm - > jitterBuffer - > Tick ( ) ;
}
}
2020-01-22 12:43:51 +01:00
if ( conctl )
{
2018-07-17 18:48:21 +02:00
conctl - > Tick ( ) ;
}
2019-04-15 01:43:10 +02:00
//MutexGuard m(queuedPacketsMutex);
2020-01-22 12:43:51 +01:00
double currentTime = GetCurrentTime ( ) ;
double rtt = GetAverageRTT ( ) ;
double packetLossTimeout = std : : max ( rtt * 2.0 , 0.1 ) ;
for ( RecentOutgoingPacket & pkt : recentOutgoingPackets )
{
if ( pkt . ackTime ! = 0.0 | | pkt . lost )
2019-04-15 01:43:10 +02:00
continue ;
2020-01-22 12:43:51 +01:00
if ( currentTime - pkt . sendTime > packetLossTimeout )
{
pkt . lost = true ;
2019-04-15 01:43:10 +02:00
sendLosses + + ;
LOGW ( " Outgoing packet lost: seq=%u, type=%s, size=%u " , pkt . seq , GetPacketTypeString ( pkt . type ) . c_str ( ) , ( unsigned int ) pkt . size ) ;
2020-01-22 12:43:51 +01:00
if ( pkt . sender )
{
2019-04-15 01:43:10 +02:00
pkt . sender - > PacketLost ( pkt . seq , pkt . type , pkt . size ) ;
2020-01-22 12:43:51 +01:00
}
else if ( pkt . type = = PKT_STREAM_DATA )
{
2019-04-15 01:43:10 +02:00
conctl - > PacketLost ( pkt . seq ) ;
}
}
}
2018-07-17 18:48:21 +02:00
}
# pragma mark - Endpoint
2020-01-22 12:43:51 +01:00
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 ;
2017-04-17 20:57:07 +02:00
memcpy ( this - > peerTag , peerTag , 16 ) ;
2020-01-22 12:43:51 +01:00
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 ;
2017-04-17 20:57:07 +02:00
}
2017-03-30 16:06:59 +02:00
2020-01-22 12:43:51 +01:00
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 ;
2019-04-15 01:43:10 +02:00
memcpy ( this - > peerTag , peerTag , 16 ) ;
2020-01-22 12:43:51 +01:00
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 ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
Endpoint : : Endpoint ( ) : address ( NetworkAddress : : Empty ( ) ) , v6address ( NetworkAddress : : Empty ( ) )
{
lastPingSeq = 0 ;
lastPingTime = 0 ;
averageRTT = 0 ;
socket = NULL ;
udpPongCount = 0 ;
2017-04-17 20:57:07 +02:00
}
2018-06-04 21:37:43 +02:00
2020-01-22 12:43:51 +01:00
const NetworkAddress & Endpoint : : GetAddress ( ) const
{
return IsIPv6Only ( ) ? ( NetworkAddress & ) v6address : ( NetworkAddress & ) address ;
2018-11-09 16:44:01 +01:00
}
2020-01-22 12:43:51 +01:00
NetworkAddress & Endpoint : : GetAddress ( )
{
return IsIPv6Only ( ) ? ( NetworkAddress & ) v6address : ( NetworkAddress & ) address ;
2018-06-04 21:37:43 +02:00
}
2020-01-22 12:43:51 +01:00
bool Endpoint : : IsIPv6Only ( ) const
{
2018-06-04 21:37:43 +02:00
return address . IsEmpty ( ) & & ! v6address . IsEmpty ( ) ;
}
2020-01-22 12:43:51 +01:00
int64_t Endpoint : : CleanID ( ) const
{
int64_t _id = id ;
if ( type = = Type : : TCP_RELAY )
{
_id = _id ^ ( ( int64_t ) FOURCC ( ' T ' , ' C ' , ' P ' , ' ' ) < < 32 ) ;
2019-04-15 01:43:10 +02:00
}
2020-01-22 12:43:51 +01:00
if ( IsIPv6Only ( ) )
{
_id = _id ^ ( ( int64_t ) FOURCC ( ' I ' , ' P ' , ' v ' , ' 6 ' ) < < 32 ) ;
2019-04-15 01:43:10 +02:00
}
return _id ;
}
2020-01-22 12:43:51 +01:00
Endpoint : : ~ Endpoint ( )
{
if ( socket )
{
2018-06-04 21:37:43 +02:00
socket - > Close ( ) ;
}
}
2018-12-30 00:24:55 +01:00
# pragma mark - AudioInputTester
2020-01-22 12:43:51 +01:00
AudioInputTester : : AudioInputTester ( std : : string deviceID ) : deviceID ( std : : move ( deviceID ) )
{
io = audio : : AudioIO : : Create ( deviceID , " default " ) ;
if ( io - > Failed ( ) )
{
2018-12-30 00:24:55 +01:00
LOGE ( " Audio IO failed " ) ;
return ;
}
2020-01-22 12:43:51 +01:00
input = io - > GetInput ( ) ;
input - > SetCallback ( [ ] ( unsigned char * data , size_t size , void * ctx ) - > size_t {
reinterpret_cast < AudioInputTester * > ( ctx ) - > Update ( reinterpret_cast < int16_t * > ( data ) , size / 2 ) ;
2018-12-30 00:24:55 +01:00
return 0 ;
2020-01-22 12:43:51 +01:00
} ,
this ) ;
2018-12-30 00:24:55 +01:00
input - > Start ( ) ;
}
2020-01-22 12:43:51 +01:00
AudioInputTester : : ~ AudioInputTester ( )
{
2018-12-30 00:24:55 +01:00
input - > Stop ( ) ;
delete io ;
}
2020-01-22 12:43:51 +01:00
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 ;
2018-12-30 00:24:55 +01:00
}
}
2020-01-22 12:43:51 +01:00
float AudioInputTester : : GetAndResetLevel ( )
{
float s = maxSample ;
maxSample = 0 ;
return s / ( float ) INT16_MAX ;
2018-12-30 00:24:55 +01:00
}