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"
# include "logging.h"
# include "threading.h"
# include "BufferOutputStream.h"
# include "BufferInputStream.h"
# include "OpusEncoder.h"
# include "OpusDecoder.h"
2017-03-30 16:06:59 +02:00
# include "VoIPServerConfig.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>
# define PKT_INIT 1
# define PKT_INIT_ACK 2
# define PKT_STREAM_STATE 3
# define PKT_STREAM_DATA 4
# define PKT_UPDATE_STREAMS 5
# define PKT_PING 6
# define PKT_PONG 7
# define PKT_STREAM_DATA_X2 8
# define PKT_STREAM_DATA_X3 9
# define PKT_LAN_ENDPOINT 10
# define PKT_NETWORK_CHANGED 11
# define PKT_SWITCH_PREF_RELAY 12
# define PKT_SWITCH_TO_P2P 13
# define PKT_NOP 14
2018-05-15 20:23:46 +02:00
# define PKT_GROUP_CALL_KEY 15
# define PKT_REQUEST_GROUP 16
2017-07-03 03:42:49 +02:00
# define IS_MOBILE_NETWORK(x) (x==NET_TYPE_GPRS || x==NET_TYPE_EDGE || x==NET_TYPE_3G || x==NET_TYPE_HSPA || x==NET_TYPE_LTE || x==NET_TYPE_OTHER_MOBILE)
# define PROTOCOL_NAME 0x50567247 // "GrVP" in little endian (reversed here)
2018-05-15 20:23:46 +02:00
# define PROTOCOL_VERSION 5
2017-07-03 03:42:49 +02:00
# define MIN_PROTOCOL_VERSION 3
# define STREAM_DATA_FLAG_LEN16 0x40
# define STREAM_DATA_FLAG_HAS_MORE_FLAGS 0x80
# define STREAM_TYPE_AUDIO 1
# define STREAM_TYPE_VIDEO 2
2018-05-15 20:23:46 +02:00
# define FOURCC(a,b,c,d) ((uint32_t)d | ((uint32_t)c << 8) | ((uint32_t)b << 16) | ((uint32_t)a << 24))
# define CODEC_OPUS_OLD 1
# define CODEC_OPUS FOURCC('O','P','U','S')
2017-07-03 03:42:49 +02:00
/*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 */
# define PFLAG_HAS_DATA 1
# define PFLAG_HAS_EXTRA 2
# define PFLAG_HAS_CALL_ID 4
# define PFLAG_HAS_PROTO 8
# define PFLAG_HAS_SEQ 16
# define PFLAG_HAS_RECENT_RECV 32
2018-05-15 20:23:46 +02:00
# define PFLAG_HAS_SENDER_TAG_HASH 64
# define STREAM_FLAG_ENABLED 1
# define STREAM_FLAG_DTX 2
# define STREAM_RFLAG_SUPPORTED 1
2017-07-03 03:42:49 +02:00
# define INIT_FLAG_DATA_SAVING_ENABLED 1
2018-05-15 20:23:46 +02:00
# define INIT_FLAG_GROUP_CALLS_SUPPORTED 2
2017-07-03 03:42:49 +02:00
# define TLID_DECRYPTED_AUDIO_BLOCK 0xDBF948C1
# define TLID_SIMPLE_AUDIO_BLOCK 0xCC0D0E76
# define TLID_UDP_REFLECTOR_PEER_INFO 0x27D9371C
# define TLID_UDP_REFLECTOR_PEER_INFO_IPV6 0x83fc73b1
# define TLID_UDP_REFLECTOR_SELF_INFO 0xc01572c7
2018-05-15 20:23:46 +02:00
# define TLID_UDP_REFLECTOR_REQUEST_PACKETS_INFO 0x1a06fc96
# define TLID_UDP_REFLECTOR_LAST_PACKETS_INFO 0x0e107305
# define TLID_VECTOR 0x1cb5c415
2017-07-03 03:42:49 +02:00
# define PAD4(x) (4-(x+(x<=253 ? 1 : 0))%4)
2018-05-15 20:23:46 +02:00
# define MAX_RECENT_PACKETS 64
2017-08-21 18:02:37 +02:00
# define MAX(a,b) (a>b ? a : b)
# define MIN(a,b) (a<b ? a : b)
2017-07-03 03:42:49 +02:00
inline int pad4 ( int x ) {
int r = PAD4 ( x ) ;
if ( r = = 4 )
return 0 ;
return r ;
}
2017-04-17 20:57:07 +02:00
using namespace tgvoip ;
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>
2017-04-17 20:57:07 +02:00
double VoIPController : : machTimebase = 0 ;
uint64_t VoIPController : : machTimestart = 0 ;
# endif
# ifdef _WIN32
int64_t VoIPController : : win32TimeScale = 0 ;
bool VoIPController : : didInitWin32TimeScale = false ;
2017-02-02 17:24:40 +01:00
# endif
# define SHA1_LENGTH 20
# define SHA256_LENGTH 32
2017-03-30 16:06:59 +02:00
# ifndef TGVOIP_USE_CUSTOM_CRYPTO
2017-12-08 21:16:12 +01:00
extern " C " {
2017-02-02 17:24:40 +01:00
# include <openssl/sha.h>
# include <openssl/aes.h>
2017-07-06 22:19:12 +02:00
# include <openssl/modes.h>
2017-02-02 17:24:40 +01:00
# include <openssl/rand.h>
2017-12-08 21:16:12 +01:00
}
2017-02-02 17:24:40 +01:00
void tgvoip_openssl_aes_ige_encrypt ( uint8_t * in , uint8_t * out , size_t length , uint8_t * key , uint8_t * iv ) {
AES_KEY akey ;
AES_set_encrypt_key ( key , 32 * 8 , & akey ) ;
AES_ige_encrypt ( in , out , length , & akey , iv , AES_ENCRYPT ) ;
}
void tgvoip_openssl_aes_ige_decrypt ( uint8_t * in , uint8_t * out , size_t length , uint8_t * key , uint8_t * iv ) {
AES_KEY akey ;
AES_set_decrypt_key ( key , 32 * 8 , & akey ) ;
AES_ige_encrypt ( in , out , length , & akey , iv , AES_DECRYPT ) ;
}
void tgvoip_openssl_rand_bytes ( uint8_t * buffer , size_t len ) {
RAND_bytes ( buffer , len ) ;
}
void tgvoip_openssl_sha1 ( uint8_t * msg , size_t len , uint8_t * output ) {
SHA1 ( msg , len , output ) ;
}
void tgvoip_openssl_sha256 ( uint8_t * msg , size_t len , uint8_t * output ) {
SHA256 ( msg , len , output ) ;
}
2017-06-06 03:44:16 +02:00
void tgvoip_openssl_aes_ctr_encrypt ( uint8_t * inout , size_t length , uint8_t * key , uint8_t * iv , uint8_t * ecount , uint32_t * num ) {
AES_KEY akey ;
AES_set_encrypt_key ( key , 32 * 8 , & akey ) ;
2017-07-06 22:19:12 +02:00
CRYPTO_ctr128_encrypt ( inout , inout , length , & akey , iv , ecount , num , ( block128_f ) AES_encrypt ) ;
2017-06-06 03:44:16 +02:00
}
2018-05-15 20:23:46 +02:00
void tgvoip_openssl_aes_cbc_encrypt ( uint8_t * in , uint8_t * out , size_t length , uint8_t * key , uint8_t * iv ) {
AES_KEY akey ;
AES_set_encrypt_key ( key , 256 , & akey ) ;
AES_cbc_encrypt ( in , out , length , & akey , iv , AES_ENCRYPT ) ;
}
void tgvoip_openssl_aes_cbc_decrypt ( uint8_t * in , uint8_t * out , size_t length , uint8_t * key , uint8_t * iv ) {
AES_KEY akey ;
AES_set_decrypt_key ( key , 256 , & akey ) ;
AES_cbc_encrypt ( in , out , length , & akey , iv , AES_DECRYPT ) ;
}
2017-04-17 20:57:07 +02:00
voip_crypto_functions_t VoIPController : : crypto = {
2017-02-02 17:24:40 +01:00
tgvoip_openssl_rand_bytes ,
tgvoip_openssl_sha1 ,
tgvoip_openssl_sha256 ,
tgvoip_openssl_aes_ige_encrypt ,
2017-06-06 03:44:16 +02:00
tgvoip_openssl_aes_ige_decrypt ,
2018-05-15 20:23:46 +02:00
tgvoip_openssl_aes_ctr_encrypt ,
tgvoip_openssl_aes_cbc_encrypt ,
tgvoip_openssl_aes_cbc_decrypt
2017-02-02 17:24:40 +01:00
} ;
# else
2017-04-17 20:57:07 +02:00
voip_crypto_functions_t VoIPController : : crypto ; // set it yourself upon initialization
# endif
# ifdef _MSC_VER
# define MSC_STACK_FALLBACK(a, b) (b)
# else
# define MSC_STACK_FALLBACK(a, b) (a)
2017-02-02 17:24:40 +01:00
# endif
2017-03-30 16:06:59 +02:00
extern FILE * tgvoipLogFile ;
2017-07-03 03:42:49 +02:00
VoIPController : : VoIPController ( ) : activeNetItfName ( " " ) ,
currentAudioInput ( " default " ) ,
currentAudioOutput ( " default " ) ,
2018-05-15 20:23:46 +02:00
outgoingPacketsBufferPool ( 1024 , 20 ) ,
2017-07-03 03:42:49 +02:00
proxyAddress ( " " ) ,
proxyUsername ( " " ) ,
2018-05-15 20:23:46 +02:00
proxyPassword ( " " ) {
2017-02-02 17:24:40 +01:00
seq = 1 ;
lastRemoteSeq = 0 ;
state = STATE_WAIT_INIT ;
audioInput = NULL ;
audioOutput = NULL ;
encoder = NULL ;
audioOutStarted = false ;
audioTimestampIn = 0 ;
audioTimestampOut = 0 ;
stopping = false ;
2017-07-03 03:42:49 +02:00
sendQueue = new BlockingQueue < PendingOutgoingPacket > ( 21 ) ;
2017-02-02 17:24:40 +01:00
memset ( recvPacketTimes , 0 , sizeof ( double ) * 32 ) ;
memset ( rttHistory , 0 , sizeof ( double ) * 32 ) ;
memset ( sendLossCountHistory , 0 , sizeof ( uint32_t ) * 32 ) ;
memset ( & stats , 0 , sizeof ( voip_stats_t ) ) ;
lastRemoteAckSeq = 0 ;
lastSentSeq = 0 ;
recvLossCount = 0 ;
packetsRecieved = 0 ;
waitingForAcks = false ;
networkType = NET_TYPE_UNKNOWN ;
echoCanceller = NULL ;
dontSendPackets = 0 ;
micMuted = false ;
currentEndpoint = NULL ;
waitingForRelayPeerInfo = false ;
allowP2p = true ;
dataSavingMode = false ;
publicEndpointsReqTime = 0 ;
connectionInitTime = 0 ;
lastRecvPacketTime = 0 ;
dataSavingRequestedByPeer = false ;
peerVersion = 0 ;
2017-04-28 13:17:56 +02:00
conctl = new CongestionControl ( ) ;
2017-02-02 17:24:40 +01:00
prevSendLossCount = 0 ;
2017-03-30 16:06:59 +02:00
receivedInit = false ;
receivedInitAck = false ;
2017-04-09 18:14:33 +02:00
peerPreferredRelay = NULL ;
2017-04-28 13:17:56 +02:00
statsDump = NULL ;
2017-06-06 03:44:16 +02:00
useTCP = false ;
2017-07-03 03:42:49 +02:00
useUDP = true ;
2017-06-06 03:44:16 +02:00
didAddTcpRelays = false ;
2017-07-03 03:42:49 +02:00
setEstablishedAt = 0 ;
udpPingCount = 0 ;
lastUdpPingTime = 0 ;
openingTcpSocket = NULL ;
proxyProtocol = PROXY_NONE ;
proxyPort = 0 ;
resolvedProxyAddress = NULL ;
2017-04-17 20:57:07 +02:00
2017-08-21 18:02:37 +02:00
signalBarCount = 0 ;
2017-07-03 03:42:49 +02:00
selectCanceller = SocketSelectCanceller : : Create ( ) ;
udpSocket = NetworkSocket : : Create ( PROTO_UDP ) ;
realUdpSocket = udpSocket ;
udpConnectivityState = UDP_UNKNOWN ;
2017-12-27 18:25:47 +01:00
echoCancellationStrength = 1 ;
2017-05-09 22:26:18 +02:00
2017-09-07 07:39:33 +02:00
outputAGC = NULL ;
outputAGCEnabled = false ;
2018-05-15 20:23:46 +02:00
peerCapabilities = 0 ;
callbacks = { 0 } ;
didReceiveGroupCallKey = false ;
didReceiveGroupCallKeyAck = false ;
didSendGroupCallKey = false ;
didSendUpgradeRequest = false ;
didInvokeUpdateCallback = false ;
connectionMaxLayer = 0 ;
useMTProto2 = false ;
setCurrentEndpointToTCP = false ;
sendThread = NULL ;
recvThread = NULL ;
tickThread = NULL ;
2017-09-07 07:39:33 +02:00
2017-04-17 20:57:07 +02:00
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 ) ;
2017-07-03 03:42:49 +02:00
reconnectingTimeout = ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " reconnecting_state_timeout " , 2.0 ) ;
2017-03-30 16:06:59 +02:00
2017-02-02 17:24:40 +01:00
# ifdef __APPLE__
2018-05-15 20:23:46 +02:00
machTimestart = 0 ;
# if TARGET_OS_OSX
if ( kCFCoreFoundationVersionNumber > = kCFCoreFoundationVersionNumber10_7 ) {
# endif
appleAudioIO = new audio : : AudioUnitIO ( ) ;
# if TARGET_OS_OSX
} else {
appleAudioIO = NULL ;
}
2017-03-30 16:06:59 +02:00
# endif
2017-02-02 17:24:40 +01:00
# endif
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
Stream stm ;
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
2017-09-07 07:39:33 +02:00
memset ( signalBarsHistory , 0 , sizeof ( signalBarsHistory ) ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
VoIPGroupController : : VoIPGroupController ( int32_t timeDifference ) {
audioMixer = new AudioMixer ( ) ;
memset ( & callbacks , 0 , sizeof ( callbacks ) ) ;
userSelfID = 0 ;
this - > timeDifference = timeDifference ;
LOGV ( " Created VoIPGroupController; timeDifference=%d " , timeDifference ) ;
}
VoIPGroupController : : ~ VoIPGroupController ( ) {
if ( audioOutput ) {
audioOutput - > Stop ( ) ;
}
LOGD ( " before stop audio mixer " ) ;
audioMixer - > Stop ( ) ;
delete audioMixer ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; p + + ) {
if ( p - > levelMeter )
delete p - > levelMeter ;
}
}
2017-04-17 20:57:07 +02:00
VoIPController : : ~ VoIPController ( ) {
LOGD ( " Entered VoIPController::~VoIPController " ) ;
2018-05-15 20:23:46 +02:00
if ( ! stopping ) {
LOGE ( " !!!!!!!!!!!!!!!!!!!! CALL controller->Stop() BEFORE DELETING THE CONTROLLER OBJECT !!!!!!!!!!!!!!!!!!!!!!!1 " ) ;
abort ( ) ;
}
2017-02-02 17:24:40 +01:00
LOGD ( " before close socket " ) ;
2017-07-03 03:42:49 +02:00
if ( udpSocket )
delete udpSocket ;
if ( udpSocket ! = realUdpSocket )
delete realUdpSocket ;
2018-05-15 20:23:46 +02:00
for ( std : : vector < Stream > : : iterator stm = incomingStreams . begin ( ) ; stm ! = incomingStreams . end ( ) ; + + stm ) {
LOGD ( " before delete jitter buffer " ) ;
if ( stm - > jitterBuffer ) {
delete stm - > jitterBuffer ;
}
LOGD ( " before stop decoder " ) ;
if ( stm - > decoder ) {
stm - > decoder - > Stop ( ) ;
}
2017-02-02 17:24:40 +01:00
}
LOGD ( " before delete audio input " ) ;
if ( audioInput ) {
delete audioInput ;
}
LOGD ( " before delete encoder " ) ;
if ( encoder ) {
encoder - > Stop ( ) ;
delete encoder ;
}
LOGD ( " before delete audio output " ) ;
if ( audioOutput ) {
delete audioOutput ;
}
2018-05-15 20:23:46 +02:00
# ifdef __APPLE__
LOGD ( " before delete AudioUnitIO " ) ;
if ( appleAudioIO ) {
delete appleAudioIO ;
}
# endif
for ( std : : vector < Stream > : : iterator stm = incomingStreams . begin ( ) ; stm ! = incomingStreams . end ( ) ; + + stm ) {
LOGD ( " before delete decoder " ) ;
if ( stm - > decoder ) {
delete stm - > decoder ;
}
2017-02-02 17:24:40 +01:00
}
LOGD ( " before delete echo canceller " ) ;
if ( echoCanceller ) {
echoCanceller - > Stop ( ) ;
delete echoCanceller ;
}
delete sendQueue ;
2017-03-30 16:06:59 +02:00
unsigned int i ;
2017-02-02 17:24:40 +01:00
for ( i = 0 ; i < queuedPackets . size ( ) ; i + + ) {
if ( queuedPackets [ i ] - > data )
free ( queuedPackets [ i ] - > data ) ;
free ( queuedPackets [ i ] ) ;
}
delete conctl ;
2017-07-03 03:42:49 +02:00
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
if ( ( * itr ) - > socket ) {
( * itr ) - > socket - > Close ( ) ;
delete ( * itr ) - > socket ;
}
2017-04-17 20:57:07 +02:00
delete * itr ;
2017-07-03 03:42:49 +02:00
}
2017-03-30 16:06:59 +02:00
if ( tgvoipLogFile ) {
FILE * log = tgvoipLogFile ;
tgvoipLogFile = NULL ;
fclose ( log ) ;
}
2017-04-28 13:17:56 +02:00
if ( statsDump )
fclose ( statsDump ) ;
2017-07-03 03:42:49 +02:00
if ( resolvedProxyAddress )
delete resolvedProxyAddress ;
delete selectCanceller ;
2017-09-07 07:39:33 +02:00
if ( outputAGC )
delete outputAGC ;
2017-07-03 03:42:49 +02:00
LOGD ( " Left VoIPController::~VoIPController " ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
void VoIPController : : Stop ( ) {
LOGD ( " Entered VoIPController::Stop " ) ;
stopping = true ;
runReceiver = false ;
LOGD ( " before shutdown socket " ) ;
if ( udpSocket )
udpSocket - > Close ( ) ;
if ( realUdpSocket ! = udpSocket )
realUdpSocket - > Close ( ) ;
selectCanceller - > CancelSelect ( ) ;
sendQueue - > Put ( PendingOutgoingPacket { 0 } ) ;
if ( openingTcpSocket )
openingTcpSocket - > Close ( ) ;
LOGD ( " before join sendThread " ) ;
if ( sendThread ) {
sendThread - > Join ( ) ;
delete sendThread ;
}
LOGD ( " before join recvThread " ) ;
if ( recvThread ) {
recvThread - > Join ( ) ;
delete recvThread ;
}
LOGD ( " before join tickThread " ) ;
if ( tickThread ) {
tickThread - > Join ( ) ;
delete tickThread ;
}
2018-05-25 21:14:45 +02:00
{
LOGD ( " Before stop audio I/O " ) ;
MutexGuard m ( audioIOMutex ) ;
if ( audioInput )
audioInput - > Stop ( ) ;
if ( audioOutput )
audioOutput - > Stop ( ) ;
}
2018-05-15 20:23:46 +02:00
LOGD ( " Left VoIPController::Stop " ) ;
}
void VoIPController : : SetRemoteEndpoints ( std : : vector < Endpoint > endpoints , bool allowP2p , int32_t connectionMaxLayer ) {
LOGW ( " Set remote endpoints, allowP2P=%d, connectionMaxLayer=%u " , allowP2p ? 1 : 0 , connectionMaxLayer ) ;
2017-02-02 17:24:40 +01:00
preferredRelay = NULL ;
2018-05-15 20:23:46 +02:00
{
MutexGuard m ( endpointsMutex ) ;
this - > endpoints . clear ( ) ;
didAddTcpRelays = false ;
useTCP = true ;
for ( std : : vector < Endpoint > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
this - > endpoints . push_back ( new Endpoint ( * itrtr ) ) ;
if ( itrtr - > type = = Endpoint : : TYPE_TCP_RELAY )
didAddTcpRelays = true ;
if ( itrtr - > type = = Endpoint : : TYPE_UDP_RELAY )
useTCP = false ;
LOGV ( " Adding endpoint: %s:%d, %s " , itrtr - > address . ToString ( ) . c_str ( ) , itrtr - > port , itrtr - > type = = Endpoint : : TYPE_UDP_RELAY ? " UDP " : " TCP " ) ;
}
2017-02-02 17:24:40 +01:00
}
currentEndpoint = this - > endpoints [ 0 ] ;
2017-04-17 20:57:07 +02:00
preferredRelay = currentEndpoint ;
2017-02-02 17:24:40 +01:00
this - > allowP2p = allowP2p ;
2018-05-15 20:23:46 +02:00
this - > connectionMaxLayer = connectionMaxLayer ;
if ( connectionMaxLayer > = 74 ) {
useMTProto2 = true ;
}
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02: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 ( ) ;
if ( udpSocket - > IsFailed ( ) ) {
SetState ( STATE_FAILED ) ;
return ;
}
2017-03-31 07:33:30 +02:00
2017-07-03 03:42:49 +02:00
//SendPacket(NULL, 0, currentEndpoint);
2017-02-02 17:24:40 +01:00
runReceiver = true ;
2018-05-15 20:23:46 +02:00
recvThread = new Thread ( new MethodPointer < VoIPController > ( & VoIPController : : RunRecvThread , this ) , NULL ) ;
recvThread - > SetName ( " VoipRecv " ) ;
recvThread - > Start ( ) ;
sendThread = new Thread ( new MethodPointer < VoIPController > ( & VoIPController : : RunSendThread , this ) , NULL ) ;
sendThread - > SetName ( " VoipSend " ) ;
sendThread - > Start ( ) ;
tickThread = new Thread ( new MethodPointer < VoIPController > ( & VoIPController : : RunTickThread , this ) , NULL ) ;
tickThread - > SetName ( " VoipTick " ) ;
tickThread - > Start ( ) ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
size_t VoIPController : : AudioInputCallback ( unsigned char * data , size_t length , void * param ) {
( ( VoIPController * ) param ) - > HandleAudioInput ( data , length ) ;
2017-02-02 17:24:40 +01:00
return 0 ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : HandleAudioInput ( unsigned char * data , size_t len ) {
2017-02-02 17:24:40 +01:00
if ( stopping )
return ;
if ( waitingForAcks | | dontSendPackets > 0 ) {
LOGV ( " waiting for RLC, dropping outgoing audio packet " ) ;
return ;
}
2017-07-03 03:42:49 +02:00
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
if ( buf ) {
BufferOutputStream pkt ( buf , outgoingPacketsBufferPool . GetSingleBufferSize ( ) ) ;
unsigned char flags = ( unsigned char ) ( len > 255 ? STREAM_DATA_FLAG_LEN16 : 0 ) ;
pkt . WriteByte ( ( unsigned char ) ( 1 | flags ) ) ; // streamID + flags
if ( len > 255 )
pkt . WriteInt16 ( ( int16_t ) len ) ;
else
pkt . WriteByte ( ( unsigned char ) len ) ;
pkt . WriteInt32 ( audioTimestampOut ) ;
pkt . WriteBytes ( data , len ) ;
PendingOutgoingPacket p {
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_STREAM_DATA ,
/*.len=*/ pkt . GetLength ( ) ,
/*.data=*/ buf ,
/*.endpoint=*/ NULL ,
} ;
sendQueue - > Put ( p ) ;
2017-02-02 17:24:40 +01:00
}
2017-07-03 03:42:49 +02:00
2018-05-15 20:23:46 +02:00
audioTimestampOut + = outgoingStreams [ 0 ] . frameDuration ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
void VoIPController : : Connect ( ) {
2017-02-02 17:24:40 +01:00
assert ( state ! = STATE_WAIT_INIT_ACK ) ;
2017-07-03 03:42:49 +02:00
if ( proxyProtocol = = PROXY_SOCKS5 ) {
resolvedProxyAddress = NetworkSocket : : ResolveDomainName ( proxyAddress ) ;
if ( ! resolvedProxyAddress ) {
LOGW ( " Error resolving proxy address %s " , proxyAddress . c_str ( ) ) ;
SetState ( STATE_FAILED ) ;
return ;
}
InitUDPProxy ( ) ;
}
2017-02-02 17:24:40 +01:00
connectionInitTime = GetCurrentTime ( ) ;
SendInit ( ) ;
}
2017-04-17 20:57:07 +02: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 ] ;
crypto . sha1 ( ( uint8_t * ) encryptionKey , 256 , sha1 ) ;
memcpy ( keyFingerprint , sha1 + ( SHA1_LENGTH - 8 ) , 8 ) ;
uint8_t sha256 [ SHA256_LENGTH ] ;
crypto . sha256 ( ( uint8_t * ) encryptionKey , 256 , sha256 ) ;
memcpy ( callID , sha256 + ( SHA256_LENGTH - 16 ) , 16 ) ;
2017-03-30 16:06:59 +02:00
this - > isOutgoing = isOutgoing ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
void VoIPGroupController : : SetGroupCallInfo ( unsigned char * encryptionKey , unsigned char * reflectorGroupTag , unsigned char * reflectorSelfTag , unsigned char * reflectorSelfSecret , unsigned char * reflectorSelfTagHash , int32_t selfUserID , IPv4Address reflectorAddress , IPv6Address reflectorAddressV6 , uint16_t reflectorPort ) {
Endpoint * e = new Endpoint ( ) ;
e - > address = reflectorAddress ;
e - > v6address = reflectorAddressV6 ;
e - > port = reflectorPort ;
memcpy ( e - > peerTag , reflectorGroupTag , 16 ) ;
e - > type = Endpoint : : TYPE_UDP_RELAY ;
endpoints . push_back ( e ) ;
groupReflector = e ;
currentEndpoint = e ;
memcpy ( this - > encryptionKey , encryptionKey , 256 ) ;
memcpy ( this - > reflectorSelfTag , reflectorSelfTag , 16 ) ;
memcpy ( this - > reflectorSelfSecret , reflectorSelfSecret , 16 ) ;
memcpy ( this - > reflectorSelfTagHash , reflectorSelfTagHash , 16 ) ;
uint8_t sha256 [ SHA256_LENGTH ] ;
crypto . sha256 ( ( uint8_t * ) encryptionKey , 256 , sha256 ) ;
memcpy ( callID , sha256 + ( SHA256_LENGTH - 16 ) , 16 ) ;
memcpy ( keyFingerprint , sha256 + ( SHA256_LENGTH - 16 ) , 8 ) ;
this - > userSelfID = selfUserID ;
//LOGD("reflectorSelfTag = %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", reflectorSelfTag[0], reflectorSelfTag[1], reflectorSelfTag[2], reflectorSelfTag[3], reflectorSelfTag[4], reflectorSelfTag[5], reflectorSelfTag[6], reflectorSelfTag[7], reflectorSelfTag[8], reflectorSelfTag[9], reflectorSelfTag[10], reflectorSelfTag[11], reflectorSelfTag[12], reflectorSelfTag[13], reflectorSelfTag[14], reflectorSelfTag[15]);
//LOGD("reflectorSelfSecret = %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", reflectorSelfSecret[0], reflectorSelfSecret[1], reflectorSelfSecret[2], reflectorSelfSecret[3], reflectorSelfSecret[4], reflectorSelfSecret[5], reflectorSelfSecret[6], reflectorSelfSecret[7], reflectorSelfSecret[8], reflectorSelfSecret[9], reflectorSelfSecret[10], reflectorSelfSecret[11], reflectorSelfSecret[12], reflectorSelfSecret[13], reflectorSelfSecret[14], reflectorSelfSecret[15]);
//LOGD("reflectorSelfTagHash = %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", reflectorSelfTagHash[0], reflectorSelfTagHash[1], reflectorSelfTagHash[2], reflectorSelfTagHash[3], reflectorSelfTagHash[4], reflectorSelfTagHash[5], reflectorSelfTagHash[6], reflectorSelfTagHash[7], reflectorSelfTagHash[8], reflectorSelfTagHash[9], reflectorSelfTagHash[10], reflectorSelfTagHash[11], reflectorSelfTagHash[12], reflectorSelfTagHash[13], reflectorSelfTagHash[14], reflectorSelfTagHash[15]);
}
void VoIPGroupController : : AddGroupCallParticipant ( int32_t userID , unsigned char * memberTagHash , unsigned char * serializedStreams , size_t streamsLength ) {
if ( userID = = userSelfID )
return ;
if ( userSelfID = = 0 )
return ;
//if(streamsLength==0)
// return;
MutexGuard m ( participantsMutex ) ;
2018-05-24 18:42:28 +02:00
//LOGV("Adding group call user %d, streams length %u, streams %X", userID, streamsLength, serializedStreams);
2018-05-15 20:23:46 +02:00
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( p - > userID = = userID ) {
LOGE ( " user %d already added " , userID ) ;
abort ( ) ;
break ;
}
}
GroupCallParticipant p ;
p . userID = userID ;
memcpy ( p . memberTagHash , memberTagHash , sizeof ( p . memberTagHash ) ) ;
p . levelMeter = new AudioLevelMeter ( ) ;
BufferInputStream ss ( serializedStreams , streamsLength ) ;
std : : vector < Stream > streams = DeserializeStreams ( ss ) ;
unsigned char audioStreamID = 0 ;
for ( std : : vector < Stream > : : iterator s = streams . begin ( ) ; s ! = streams . end ( ) ; + + s ) {
s - > userID = userID ;
if ( s - > type = = STREAM_TYPE_AUDIO & & s - > codec = = CODEC_OPUS & & ! audioStreamID ) {
audioStreamID = s - > id ;
s - > jitterBuffer = new JitterBuffer ( NULL , s - > frameDuration ) ;
if ( s - > frameDuration > 50 )
s - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_60 " , 2 ) ) ;
else if ( s - > frameDuration > 30 )
s - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_40 " , 4 ) ) ;
else
s - > jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_20 " , 6 ) ) ;
s - > callbackWrapper = new CallbackWrapper ( ) ;
s - > decoder = new OpusDecoder ( s - > callbackWrapper , false ) ;
s - > decoder - > SetJitterBuffer ( s - > jitterBuffer ) ;
s - > decoder - > SetFrameDuration ( s - > frameDuration ) ;
s - > decoder - > SetDTX ( true ) ;
s - > decoder - > SetLevelMeter ( p . levelMeter ) ;
audioMixer - > AddInput ( s - > callbackWrapper ) ;
}
incomingStreams . push_back ( * s ) ;
}
if ( ! audioStreamID ) {
LOGW ( " User %d has no usable audio stream " , userID ) ;
}
p . streams . insert ( p . streams . end ( ) , streams . begin ( ) , streams . end ( ) ) ;
participants . push_back ( p ) ;
LOGI ( " Added group call participant %d " , userID ) ;
}
void VoIPGroupController : : RemoveGroupCallParticipant ( int32_t userID ) {
MutexGuard m ( participantsMutex ) ;
std : : vector < Stream > : : iterator stm = incomingStreams . begin ( ) ;
while ( stm ! = incomingStreams . end ( ) ) {
if ( stm - > userID = = userID ) {
LOGI ( " Removed stream %d belonging to user %d " , stm - > id , userID ) ;
audioMixer - > RemoveInput ( stm - > callbackWrapper ) ;
stm - > decoder - > Stop ( ) ;
delete stm - > decoder ;
delete stm - > jitterBuffer ;
delete stm - > callbackWrapper ;
stm = incomingStreams . erase ( stm ) ;
continue ;
}
+ + stm ;
}
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( p - > userID = = userID ) {
if ( p - > levelMeter )
delete p - > levelMeter ;
participants . erase ( p ) ;
LOGI ( " Removed group call participant %d " , userID ) ;
break ;
}
}
}
std : : vector < VoIPController : : Stream > VoIPGroupController : : DeserializeStreams ( BufferInputStream & in ) {
std : : vector < Stream > res ;
try {
unsigned char count = in . ReadByte ( ) ;
for ( unsigned char i = 0 ; i < count ; i + + ) {
uint16_t len = ( uint16_t ) in . ReadInt16 ( ) ;
BufferInputStream inner = in . GetPartBuffer ( len , true ) ;
Stream s = { 0 } ;
s . id = inner . ReadByte ( ) ;
s . type = inner . ReadByte ( ) ;
s . codec = ( uint32_t ) inner . ReadInt32 ( ) ;
uint32_t flags = ( uint32_t ) inner . ReadInt32 ( ) ;
s . enabled = ( flags & STREAM_FLAG_ENABLED ) = = STREAM_FLAG_ENABLED ;
s . frameDuration = ( uint16_t ) inner . ReadInt16 ( ) ;
res . push_back ( s ) ;
}
} catch ( std : : out_of_range & x ) {
LOGW ( " Error deserializing streams: %s " , x . what ( ) ) ;
}
return res ;
}
void VoIPGroupController : : SetParticipantStreams ( int32_t userID , unsigned char * serializedStreams , size_t length ) {
LOGD ( " Set participant streams for %d " , userID ) ;
MutexGuard m ( participantsMutex ) ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( p - > userID = = userID ) {
BufferInputStream in ( serializedStreams , length ) ;
std : : vector < Stream > streams = DeserializeStreams ( in ) ;
for ( std : : vector < Stream > : : iterator ns = streams . begin ( ) ; ns ! = streams . end ( ) ; + + ns ) {
bool found = false ;
for ( std : : vector < Stream > : : iterator s = p - > streams . begin ( ) ; s ! = p - > streams . end ( ) ; + + s ) {
if ( s - > id = = ns - > id ) {
s - > enabled = ns - > enabled ;
if ( groupCallbacks . participantAudioStateChanged )
groupCallbacks . participantAudioStateChanged ( this , userID , s - > enabled ) ;
found = true ;
break ;
}
}
if ( ! found ) {
LOGW ( " Tried to add stream %d for user %d but adding/removing streams is not supported " , ns - > id , userID ) ;
}
}
break ;
}
}
}
size_t VoIPGroupController : : GetInitialStreams ( unsigned char * buf , size_t size ) {
BufferOutputStream s ( buf , size ) ;
s . WriteByte ( 1 ) ; // streams count
s . WriteInt16 ( 12 ) ; // this object length
s . WriteByte ( 1 ) ; // stream id
s . WriteByte ( STREAM_TYPE_AUDIO ) ;
s . WriteInt32 ( CODEC_OPUS ) ;
s . WriteInt32 ( STREAM_FLAG_ENABLED | STREAM_FLAG_DTX ) ; // flags
s . WriteInt16 ( 60 ) ; // frame duration
return s . GetLength ( ) ;
}
2017-07-03 03:42:49 +02:00
uint32_t VoIPController : : GenerateOutSeq ( ) {
return seq + + ;
}
void VoIPController : : WritePacketHeader ( uint32_t pseq , BufferOutputStream * s , unsigned char type , uint32_t length ) {
2017-02-02 17:24:40 +01:00
uint32_t acks = 0 ;
int i ;
for ( i = 0 ; i < 32 ; i + + ) {
if ( recvPacketTimes [ i ] > 0 )
acks | = 1 ;
if ( i < 31 )
acks < < = 1 ;
}
if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK ) {
s - > WriteInt32 ( TLID_DECRYPTED_AUDIO_BLOCK ) ;
int64_t randomID ;
crypto . rand_bytes ( ( uint8_t * ) & randomID , 8 ) ;
s - > WriteInt64 ( randomID ) ;
unsigned char randBytes [ 7 ] ;
crypto . rand_bytes ( randBytes , 7 ) ;
s - > WriteByte ( 7 ) ;
2017-03-30 16:06:59 +02:00
s - > WriteBytes ( randBytes , 7 ) ;
2017-02-02 17:24:40 +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 ;
}
pflags | = ( ( uint32_t ) type ) < < 24 ;
s - > WriteInt32 ( pflags ) ;
if ( pflags & PFLAG_HAS_CALL_ID ) {
s - > WriteBytes ( callID , 16 ) ;
}
s - > WriteInt32 ( lastRemoteSeq ) ;
s - > WriteInt32 ( pseq ) ;
s - > WriteInt32 ( acks ) ;
if ( pflags & PFLAG_HAS_PROTO ) {
s - > WriteInt32 ( PROTOCOL_NAME ) ;
}
if ( length > 0 ) {
if ( length < = 253 ) {
s - > WriteByte ( ( unsigned char ) length ) ;
} else {
s - > WriteByte ( 254 ) ;
2017-03-30 16:06:59 +02:00
s - > WriteByte ( ( unsigned char ) ( length & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 8 ) & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 16 ) & 0xFF ) ) ;
2017-02-02 17:24:40 +01:00
}
}
} else {
s - > WriteInt32 ( TLID_SIMPLE_AUDIO_BLOCK ) ;
int64_t randomID ;
crypto . rand_bytes ( ( uint8_t * ) & randomID , 8 ) ;
s - > WriteInt64 ( randomID ) ;
unsigned char randBytes [ 7 ] ;
crypto . rand_bytes ( randBytes , 7 ) ;
s - > WriteByte ( 7 ) ;
2017-03-30 16:06:59 +02:00
s - > WriteBytes ( randBytes , 7 ) ;
2017-02-02 17:24:40 +01:00
uint32_t lenWithHeader = length + 13 ;
if ( lenWithHeader > 0 ) {
if ( lenWithHeader < = 253 ) {
s - > WriteByte ( ( unsigned char ) lenWithHeader ) ;
} else {
s - > WriteByte ( 254 ) ;
2017-03-30 16:06:59 +02:00
s - > WriteByte ( ( unsigned char ) ( lenWithHeader & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( lenWithHeader > > 8 ) & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( lenWithHeader > > 16 ) & 0xFF ) ) ;
2017-02-02 17:24:40 +01:00
}
}
s - > WriteByte ( type ) ;
s - > WriteInt32 ( lastRemoteSeq ) ;
s - > WriteInt32 ( pseq ) ;
s - > WriteInt32 ( acks ) ;
}
if ( type = = PKT_STREAM_DATA | | type = = PKT_STREAM_DATA_X2 | | type = = PKT_STREAM_DATA_X3 )
conctl - > PacketSent ( pseq , length ) ;
2018-05-15 20:23:46 +02:00
MutexGuard m ( queuedPacketsMutex ) ;
recentOutgoingPackets . push_back ( RecentOutgoingPacket {
pseq ,
0 ,
GetCurrentTime ( ) ,
0
} ) ;
while ( recentOutgoingPackets . size ( ) > MAX_RECENT_PACKETS )
recentOutgoingPackets . erase ( recentOutgoingPackets . begin ( ) ) ;
2017-02-02 17:24:40 +01:00
lastSentSeq = pseq ;
//LOGI("packet header size %d", s->GetLength());
}
2017-04-17 20:57:07 +02:00
void VoIPController : : UpdateAudioBitrate ( ) {
2017-02-02 17:24:40 +01:00
if ( encoder ) {
2017-03-30 16:06:59 +02:00
if ( dataSavingMode | | dataSavingRequestedByPeer ) {
maxBitrate = maxAudioBitrateSaving ;
encoder - > SetBitrate ( initAudioBitrateSaving ) ;
} else if ( networkType = = NET_TYPE_GPRS ) {
maxBitrate = maxAudioBitrateGPRS ;
encoder - > SetBitrate ( initAudioBitrateGPRS ) ;
} else if ( networkType = = NET_TYPE_EDGE ) {
maxBitrate = maxAudioBitrateEDGE ;
encoder - > SetBitrate ( initAudioBitrateEDGE ) ;
2017-02-02 17:24:40 +01:00
} else {
2017-03-30 16:06:59 +02:00
maxBitrate = maxAudioBitrate ;
encoder - > SetBitrate ( initAudioBitrate ) ;
2017-02-02 17:24:40 +01:00
}
}
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SendInit ( ) {
2018-05-15 20:23:46 +02:00
{
MutexGuard m ( endpointsMutex ) ;
uint32_t initSeq = GenerateOutSeq ( ) ;
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
if ( ( * itr ) - > type = = Endpoint : : TYPE_TCP_RELAY & & ! useTCP )
continue ;
unsigned char * pkt = outgoingPacketsBufferPool . Get ( ) ;
if ( ! pkt ) {
LOGW ( " can't send init, queue overflow " ) ;
continue ;
}
BufferOutputStream out ( pkt , outgoingPacketsBufferPool . GetSingleBufferSize ( ) ) ;
out . WriteInt32 ( PROTOCOL_VERSION ) ;
out . WriteInt32 ( MIN_PROTOCOL_VERSION ) ;
uint32_t flags = 0 ;
if ( config . enableCallUpgrade )
flags | = INIT_FLAG_GROUP_CALLS_SUPPORTED ;
if ( dataSavingMode )
flags | = INIT_FLAG_DATA_SAVING_ENABLED ;
out . WriteInt32 ( flags ) ;
if ( connectionMaxLayer < 74 ) {
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
} else {
out . WriteByte ( 1 ) ;
out . WriteInt32 ( CODEC_OPUS ) ;
out . WriteByte ( 0 ) ;
}
sendQueue - > Put ( PendingOutgoingPacket {
/*.seq=*/ initSeq ,
/*.type=*/ PKT_INIT ,
/*.len=*/ out . GetLength ( ) ,
/*.data=*/ pkt ,
/*.endpoint=*/ * itr
} ) ;
2017-07-03 03:42:49 +02:00
}
2017-03-30 16:06:59 +02:00
}
2017-02-02 17:24:40 +01:00
SetState ( STATE_WAIT_INIT_ACK ) ;
}
2018-05-15 20:23:46 +02:00
void VoIPGroupController : : SendInit ( ) {
SendRecentPacketsRequest ( ) ;
}
2017-07-03 03:42:49 +02:00
void VoIPController : : InitUDPProxy ( ) {
if ( realUdpSocket ! = udpSocket ) {
udpSocket - > Close ( ) ;
delete udpSocket ;
udpSocket = realUdpSocket ;
}
NetworkSocket * tcp = NetworkSocket : : Create ( PROTO_TCP ) ;
tcp - > Connect ( resolvedProxyAddress , proxyPort ) ;
if ( tcp - > IsFailed ( ) ) {
SetState ( STATE_FAILED ) ;
tcp - > Close ( ) ;
delete tcp ;
return ;
}
NetworkSocketSOCKS5Proxy * udpProxy = new NetworkSocketSOCKS5Proxy ( tcp , udpSocket , proxyUsername , proxyPassword ) ;
udpProxy - > InitConnection ( ) ;
udpProxy - > Open ( ) ;
if ( udpProxy - > IsFailed ( ) ) {
udpProxy - > Close ( ) ;
delete udpProxy ;
useTCP = true ;
useUDP = false ;
udpConnectivityState = UDP_NOT_AVAILABLE ;
} else {
udpSocket = udpProxy ;
}
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
void VoIPController : : RunRecvThread ( void * arg ) {
2017-02-02 17:24:40 +01:00
LOGI ( " Receive thread starting " ) ;
2018-05-15 20:23:46 +02:00
unsigned char * buffer = ( unsigned char * ) malloc ( 1500 ) ;
NetworkPacket packet = { 0 } ;
2017-02-02 17:24:40 +01:00
while ( runReceiver ) {
2017-04-17 20:57:07 +02:00
packet . data = buffer ;
2018-05-15 20:23:46 +02:00
packet . length = 1500 ;
2017-07-03 03:42:49 +02:00
std : : vector < NetworkSocket * > readSockets ;
std : : vector < NetworkSocket * > errorSockets ;
readSockets . push_back ( realUdpSocket ) ;
errorSockets . push_back ( realUdpSocket ) ;
//if(useTCP){
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
2018-05-15 20:23:46 +02:00
if ( ( * itr ) - > type = = Endpoint : : TYPE_TCP_RELAY ) {
2017-07-03 03:42:49 +02:00
if ( ( * itr ) - > socket ) {
readSockets . push_back ( ( * itr ) - > socket ) ;
errorSockets . push_back ( ( * itr ) - > socket ) ;
}
}
}
//}
bool selRes = NetworkSocket : : Select ( readSockets , errorSockets , selectCanceller ) ;
if ( ! selRes ) {
LOGV ( " Select canceled " ) ;
continue ;
}
if ( ! runReceiver )
return ;
if ( ! errorSockets . empty ( ) ) {
if ( std : : find ( errorSockets . begin ( ) , errorSockets . end ( ) , realUdpSocket ) ! = errorSockets . end ( ) ) {
LOGW ( " UDP socket failed " ) ;
SetState ( STATE_FAILED ) ;
return ;
}
}
NetworkSocket * socket = NULL ;
if ( std : : find ( readSockets . begin ( ) , readSockets . end ( ) , realUdpSocket ) ! = readSockets . end ( ) ) {
socket = udpSocket ;
} else if ( readSockets . size ( ) > 0 ) {
socket = readSockets [ 0 ] ;
} else {
LOGI ( " no sockets to read from " ) ;
2018-05-15 20:23:46 +02:00
MutexGuard m ( endpointsMutex ) ;
2017-07-03 03:42:49 +02:00
for ( std : : vector < NetworkSocket * > : : iterator itr = errorSockets . begin ( ) ; itr ! = errorSockets . end ( ) ; + + itr ) {
for ( std : : vector < Endpoint * > : : iterator e = endpoints . begin ( ) ; e ! = endpoints . end ( ) ; + + e ) {
if ( ( * e ) - > socket & & ( * e ) - > socket = = * itr ) {
( * e ) - > socket - > Close ( ) ;
delete ( * e ) - > socket ;
( * e ) - > socket = NULL ;
LOGI ( " Closing failed TCP socket for %s:%u " , ( * e ) - > address . ToString ( ) . c_str ( ) , ( * e ) - > port ) ;
break ;
}
}
}
continue ;
}
2017-04-17 20:57:07 +02:00
socket - > Receive ( & packet ) ;
if ( ! packet . address ) {
LOGE ( " Packet has null address. This shouldn't happen. " ) ;
continue ;
2017-03-31 07:33:30 +02:00
}
2017-04-17 20:57:07 +02:00
size_t len = packet . length ;
2017-05-09 22:26:18 +02:00
if ( ! len ) {
LOGE ( " Packet has zero length. " ) ;
continue ;
}
2017-06-07 17:46:59 +02:00
//LOGV("Received %d bytes from %s:%d at %.5lf", len, packet.address->ToString().c_str(), packet.port, GetCurrentTime());
2017-04-17 20:57:07 +02:00
Endpoint * srcEndpoint = NULL ;
IPv4Address * src4 = dynamic_cast < IPv4Address * > ( packet . address ) ;
if ( src4 ) {
2018-05-15 20:23:46 +02:00
MutexGuard m ( endpointsMutex ) ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
2017-05-24 02:31:35 +02:00
if ( ( * itrtr ) - > address = = * src4 & & ( * itrtr ) - > port = = packet . port ) {
2018-05-15 20:23:46 +02:00
if ( ( ( * itrtr ) - > type ! = Endpoint : : TYPE_TCP_RELAY & & packet . protocol = = PROTO_UDP ) | | ( ( * itrtr ) - > type = = Endpoint : : TYPE_TCP_RELAY & & packet . protocol = = PROTO_TCP ) ) {
2017-06-06 03:44:16 +02:00
srcEndpoint = * itrtr ;
break ;
}
2017-03-30 16:06:59 +02:00
}
2017-02-02 17:24:40 +01:00
}
}
2017-04-17 20:57:07 +02:00
2017-02-02 17:24:40 +01:00
if ( ! srcEndpoint ) {
2017-04-17 20:57:07 +02:00
LOGW ( " Received a packet from unknown source %s:%u " , packet . address - > ToString ( ) . c_str ( ) , packet . port ) ;
2017-02-02 17:24:40 +01:00
continue ;
}
if ( len < = 0 ) {
2017-04-17 20:57:07 +02:00
//LOGW("error receiving: %d / %s", errno, strerror(errno));
2017-02-02 17:24:40 +01:00
continue ;
}
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesRecvdMobile + = ( uint64_t ) len ;
else
stats . bytesRecvdWifi + = ( uint64_t ) len ;
2017-03-30 16:06:59 +02:00
try {
2018-05-15 20:23:46 +02:00
ProcessIncomingPacket ( packet , srcEndpoint ) ;
} catch ( std : : out_of_range x ) {
LOGW ( " Error parsing packet: %s " , x . what ( ) ) ;
}
}
free ( buffer ) ;
LOGI ( " === recv thread exiting === " ) ;
}
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
void VoIPController : : RunSendThread ( void * arg ) {
unsigned char buf [ 1500 ] ;
while ( runReceiver ) {
PendingOutgoingPacket pkt = sendQueue - > GetBlocking ( ) ;
if ( pkt . data ) {
MutexGuard m ( endpointsMutex ) ;
Endpoint * endpoint = pkt . endpoint ? pkt . endpoint : currentEndpoint ;
if ( ( endpoint - > type = = Endpoint : : TYPE_TCP_RELAY & & useTCP ) | | ( endpoint - > type ! = Endpoint : : TYPE_TCP_RELAY & & useUDP ) ) {
BufferOutputStream p ( buf , sizeof ( buf ) ) ;
WritePacketHeader ( pkt . seq , & p , pkt . type , ( uint32_t ) pkt . len ) ;
p . WriteBytes ( pkt . data , pkt . len ) ;
SendPacket ( p . GetBuffer ( ) , p . GetLength ( ) , endpoint , pkt ) ;
}
outgoingPacketsBufferPool . Reuse ( pkt . data ) ;
} else {
LOGE ( " tried to send null packet " ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
LOGI ( " === send thread exiting === " ) ;
}
void VoIPController : : ProcessIncomingPacket ( NetworkPacket & packet , Endpoint * srcEndpoint ) {
unsigned char * buffer = packet . data ;
size_t len = packet . length ;
BufferInputStream in ( buffer , ( size_t ) len ) ;
if ( memcmp ( buffer , srcEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY | | srcEndpoint - > type = = Endpoint : : TYPE_TCP_RELAY ? ( void * ) srcEndpoint - > peerTag : ( void * ) callID , 16 ) ! = 0 ) {
LOGW ( " Received packet has wrong peerTag " ) ;
return ;
}
in . Seek ( 16 ) ;
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 ) {
// relay special request response
in . Seek ( 16 + 12 ) ;
uint32_t tlid = ( uint32_t ) in . ReadInt32 ( ) ;
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 ( ) ;
unsigned char myIP [ 16 ] ;
in . ReadBytes ( myIP , 16 ) ;
/*int32_t myPort=*/ in . ReadInt32 ( ) ;
//udpConnectivityState=UDP_AVAILABLE;
//LOGV("Received UDP ping reply from %s:%d: date=%d, queryID=%lld, my IP=%s, my port=%d", srcEndpoint->address.ToString().c_str(), srcEndpoint->port, date, queryID, IPv6Address(myIP).ToString().c_str(), myPort);
srcEndpoint - > udpPongCount + + ;
}
} else if ( tlid = = TLID_UDP_REFLECTOR_PEER_INFO ) {
if ( waitingForRelayPeerInfo & & in . Remaining ( ) > = 16 ) {
MutexGuard _m ( endpointsMutex ) ;
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 ( ) ;
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
Endpoint * ep = * itrtr ;
if ( ep - > type = = Endpoint : : TYPE_UDP_P2P_INET ) {
if ( currentEndpoint = = ep )
currentEndpoint = preferredRelay ;
delete ep ;
endpoints . erase ( itrtr ) ;
break ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
Endpoint * ep = * itrtr ;
if ( ep - > type = = Endpoint : : TYPE_UDP_P2P_LAN ) {
if ( currentEndpoint = = ep )
currentEndpoint = preferredRelay ;
delete ep ;
endpoints . erase ( itrtr ) ;
break ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
IPv4Address _peerAddr ( peerAddr ) ;
IPv6Address emptyV6 ( " ::0 " ) ;
unsigned char peerTag [ 16 ] ;
endpoints . push_back ( new Endpoint ( 0 , ( uint16_t ) peerPort , _peerAddr , emptyV6 , Endpoint : : TYPE_UDP_P2P_INET , peerTag ) ) ;
LOGW ( " Received reflector peer info, my=%08X:%u, peer=%08X:%u " , myAddr , myPort , peerAddr , peerPort ) ;
if ( myAddr = = peerAddr ) {
LOGW ( " Detected LAN " ) ;
IPv4Address lanAddr ( 0 ) ;
udpSocket - > GetLocalInterfaceInfo ( & lanAddr , NULL ) ;
BufferOutputStream pkt ( 8 ) ;
pkt . WriteInt32 ( lanAddr . GetAddress ( ) ) ;
pkt . WriteInt32 ( udpSocket - > GetLocalPort ( ) ) ;
SendPacketReliably ( PKT_LAN_ENDPOINT , pkt . GetBuffer ( ) , pkt . GetLength ( ) , 0.5 , 10 ) ;
}
waitingForRelayPeerInfo = false ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
} else {
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 ;
}
if ( in . Remaining ( ) < 40 ) {
LOGV ( " Received packet is too small " ) ;
return ;
}
bool retryWith2 = false ;
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02: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
if ( memcmp ( fingerprint , keyFingerprint , 8 ) ! = 0 ) {
LOGW ( " Received packet has wrong key fingerprint " ) ;
2018-05-15 20:23:46 +02:00
return ;
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 ) ] ;
if ( in . Remaining ( ) > sizeof ( aesOut ) )
return ;
2017-04-28 13:17:56 +02: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 ] ;
2018-05-15 20:23:46 +02:00
uint32_t _len = ( uint32_t ) _in . ReadInt32 ( ) ;
if ( _len > _in . Remaining ( ) )
_len = _in . Remaining ( ) ;
crypto . sha1 ( ( uint8_t * ) ( aesOut ) , ( size_t ) ( _len + 4 ) , sha ) ;
2017-02-02 17:24:40 +01:00
if ( memcmp ( msgHash , sha + ( SHA1_LENGTH - 16 ) , 16 ) ! = 0 ) {
LOGW ( " Received packet has wrong hash after decryption " ) ;
2018-05-15 20:23:46 +02:00
if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK )
retryWith2 = true ;
else
return ;
} else {
memcpy ( buffer + in . GetOffset ( ) , aesOut , in . Remaining ( ) ) ;
in . ReadInt32 ( ) ;
}
}
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
if ( useMTProto2 | | retryWith2 ) {
in . Seek ( 16 ) ; // peer tag
unsigned char fingerprint [ 8 ] , msgKey [ 16 ] ;
in . ReadBytes ( fingerprint , 8 ) ;
if ( memcmp ( fingerprint , keyFingerprint , 8 ) ! = 0 ) {
LOGW ( " Received packet has wrong key fingerprint " ) ;
return ;
}
in . ReadBytes ( msgKey , 16 ) ;
unsigned char decrypted [ 1500 ] ;
unsigned char aesKey [ 32 ] , aesIv [ 32 ] ;
KDF2 ( msgKey , isOutgoing ? 8 : 0 , aesKey , aesIv ) ;
size_t decryptedLen = in . Remaining ( ) ;
if ( decryptedLen > sizeof ( decrypted ) )
return ;
//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), decryptedLen-4);
uint8_t * decryptOffset = packet . data + in . GetOffset ( ) ;
if ( ( ( ( intptr_t ) decryptOffset ) % sizeof ( long ) ) ! = 0 ) {
LOGE ( " alignment2 packet.data+in.GetOffset() " ) ;
}
if ( decryptedLen % sizeof ( long ) ! = 0 ) {
LOGE ( " alignment2 decryptedLen " ) ;
}
crypto . aes_ige_decrypt ( packet . data + in . GetOffset ( ) , decrypted , decryptedLen , aesKey , aesIv ) ;
in = BufferInputStream ( decrypted , decryptedLen ) ;
//LOGD("received packet length: %d", in.ReadInt32());
BufferOutputStream buf ( decryptedLen + 32 ) ;
size_t x = isOutgoing ? 8 : 0 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( decrypted + 4 , decryptedLen - 4 ) ;
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
if ( memcmp ( msgKey , msgKeyLarge + 8 , 16 ) ! = 0 ) {
LOGW ( " Received packet has wrong hash " ) ;
return ;
}
uint32_t innerLen = ( uint32_t ) in . ReadInt32 ( ) ;
if ( innerLen > decryptedLen - 4 ) {
2018-05-24 18:42:28 +02:00
LOGW ( " Received packet has wrong inner length (%d with total of %u) " , innerLen , ( unsigned int ) decryptedLen ) ;
2018-05-15 20:23:46 +02:00
return ;
}
if ( decryptedLen - innerLen < 12 ) {
2018-05-24 18:42:28 +02:00
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
}
2018-05-15 20:23:46 +02:00
memcpy ( buffer , decrypted + 4 , innerLen ) ;
in = BufferInputStream ( buffer , ( size_t ) innerLen ) ;
if ( retryWith2 ) {
LOGD ( " Successfully decrypted packet in MTProto2.0 fallback, upgrading " ) ;
useMTProto2 = true ;
}
}
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
lastRecvPacketTime = GetCurrentTime ( ) ;
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
/*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
2017-02-02 17:24:40 +01:00
simpleAudioBlock random_id : long random_bytes : string raw_data : string = DecryptedAudioBlock ;
*/
2018-05-15 20:23:46 +02:00
uint32_t ackId , pseq , acks ;
unsigned char type ;
uint32_t tlid = ( uint32_t ) in . ReadInt32 ( ) ;
uint32_t packetInnerLen = 0 ;
if ( tlid = = TLID_DECRYPTED_AUDIO_BLOCK ) {
in . ReadInt64 ( ) ; // random id
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 ) ) {
LOGW ( " Received packet doesn't have PFLAG_HAS_SEQ, PFLAG_HAS_RECENT_RECV, or both " ) ;
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
return ;
}
if ( flags & PFLAG_HAS_CALL_ID ) {
unsigned char pktCallID [ 16 ] ;
in . ReadBytes ( pktCallID , 16 ) ;
if ( memcmp ( pktCallID , callID , 16 ) ! = 0 ) {
LOGW ( " Received packet has wrong call id " ) ;
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
lastError = ERROR_UNKNOWN ;
SetState ( STATE_FAILED ) ;
return ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02: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 ) {
LOGW ( " Received packet uses wrong protocol " ) ;
lastError = ERROR_INCOMPATIBLE ;
SetState ( STATE_FAILED ) ;
return ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
if ( flags & PFLAG_HAS_EXTRA ) {
uint32_t extraLen = ( uint32_t ) in . ReadTlLength ( ) ;
in . Seek ( in . GetOffset ( ) + extraLen + pad4 ( extraLen ) ) ;
}
if ( flags & PFLAG_HAS_DATA ) {
2017-04-28 13:17:56 +02:00
packetInnerLen = in . ReadTlLength ( ) ;
2018-05-15 20:23:46 +02:00
}
} else if ( tlid = = TLID_SIMPLE_AUDIO_BLOCK ) {
in . ReadInt64 ( ) ; // random id
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 ( ) ;
} else {
LOGW ( " Received a packet of unknown type %08X " , tlid ) ;
return ;
}
if ( type = = PKT_GROUP_CALL_KEY & & didSendGroupCallKey ) {
LOGE ( " Received group call key after we sent one " ) ;
return ;
}
packetsRecieved + + ;
if ( seqgt ( pseq , lastRemoteSeq ) ) {
uint32_t diff = pseq - lastRemoteSeq ;
if ( diff > 31 ) {
memset ( recvPacketTimes , 0 , 32 * sizeof ( double ) ) ;
2017-02-02 17:24:40 +01:00
} else {
2018-05-15 20:23:46 +02:00
memmove ( & recvPacketTimes [ diff ] , recvPacketTimes , ( 32 - diff ) * sizeof ( double ) ) ;
if ( diff > 1 ) {
memset ( recvPacketTimes , 0 , diff * sizeof ( double ) ) ;
}
recvPacketTimes [ 0 ] = GetCurrentTime ( ) ;
}
lastRemoteSeq = pseq ;
} else if ( ! seqgt ( pseq , lastRemoteSeq ) & & lastRemoteSeq - pseq < 32 ) {
if ( recvPacketTimes [ lastRemoteSeq - pseq ] ! = 0 ) {
LOGW ( " Received duplicated packet for seq %u " , pseq ) ;
2017-05-09 22:26:18 +02:00
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
recvPacketTimes [ lastRemoteSeq - pseq ] = GetCurrentTime ( ) ;
} else if ( lastRemoteSeq - pseq > = 32 ) {
LOGW ( " Packet %u is out of order and too late " , pseq ) ;
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
return ;
}
if ( seqgt ( ackId , lastRemoteAckSeq ) ) {
//uint32_t diff=ackId-lastRemoteAckSeq;
/*if(diff>31){
memset ( remoteAcks , 0 , 32 * sizeof ( double ) ) ;
} else {
memmove ( & remoteAcks [ diff ] , remoteAcks , ( 32 - diff ) * sizeof ( double ) ) ;
if ( diff > 1 ) {
memset ( remoteAcks , 0 , diff * sizeof ( double ) ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
remoteAcks [ 0 ] = GetCurrentTime ( ) ;
} */
MutexGuard _m ( queuedPacketsMutex ) ;
if ( waitingForAcks & & lastRemoteAckSeq > = firstSentPing ) {
memset ( rttHistory , 0 , 32 * sizeof ( double ) ) ;
waitingForAcks = false ;
dontSendPackets = 10 ;
LOGI ( " resuming sending " ) ;
}
lastRemoteAckSeq = ackId ;
conctl - > PacketAcknowledged ( ackId ) ;
unsigned int i ;
for ( i = 0 ; i < 31 ; i + + ) {
for ( std : : vector < RecentOutgoingPacket > : : iterator itr = recentOutgoingPackets . begin ( ) ; itr ! = recentOutgoingPackets . end ( ) ; + + itr ) {
if ( itr - > ackTime ! = 0 )
continue ;
if ( ( ( acks > > ( 31 - i ) ) & 1 ) & & itr - > seq = = ackId - ( i + 1 ) ) {
itr - > ackTime = GetCurrentTime ( ) ;
conctl - > PacketAcknowledged ( itr - > seq ) ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
/*if(remoteAcks[i+1]==0){
if ( ( acks > > ( 31 - i ) ) & 1 ) {
remoteAcks [ i + 1 ] = GetCurrentTime ( ) ;
conctl - > PacketAcknowledged ( ackId - ( i + 1 ) ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
} */
}
for ( i = 0 ; i < queuedPackets . size ( ) ; i + + ) {
voip_queued_packet_t * qp = queuedPackets [ i ] ;
int j ;
bool didAck = false ;
for ( j = 0 ; j < 16 ; j + + ) {
LOGD ( " queued packet %u, seq %u=%u " , i , j , qp - > seqs [ j ] ) ;
if ( qp - > seqs [ j ] = = 0 )
break ;
int remoteAcksIndex = lastRemoteAckSeq - qp - > seqs [ j ] ;
//LOGV("remote acks index %u, value %f", remoteAcksIndex, remoteAcksIndex>=0 && remoteAcksIndex<32 ? remoteAcks[remoteAcksIndex] : -1);
if ( seqgt ( lastRemoteAckSeq , qp - > seqs [ j ] ) & & remoteAcksIndex > = 0 & & remoteAcksIndex < 32 ) {
for ( std : : vector < RecentOutgoingPacket > : : iterator itr = recentOutgoingPackets . begin ( ) ; itr ! = recentOutgoingPackets . end ( ) ; + + itr ) {
if ( itr - > seq = = qp - > seqs [ j ] & & itr - > ackTime > 0 ) {
LOGD ( " did ack seq %u, removing " , qp - > seqs [ j ] ) ;
didAck = true ;
break ;
}
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( didAck )
break ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
if ( didAck ) {
if ( qp - > type = = PKT_GROUP_CALL_KEY & & ! didReceiveGroupCallKeyAck ) {
didReceiveGroupCallKeyAck = true ;
if ( callbacks . groupCallKeySent )
callbacks . groupCallKeySent ( this ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( qp - > data )
free ( qp - > data ) ;
free ( qp ) ;
queuedPackets . erase ( queuedPackets . begin ( ) + i ) ;
i - - ;
continue ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
}
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
if ( srcEndpoint ! = 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 ;
LOGI ( " Peer network address probably changed, switching to relay " ) ;
if ( allowP2p )
SendPublicEndpointsRequest ( ) ;
2017-02-02 17:24:40 +01:00
}
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);
if ( type = = PKT_INIT ) {
LOGD ( " Received init " ) ;
if ( ! receivedInit ) {
receivedInit = true ;
if ( ( srcEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY & & udpConnectivityState ! = UDP_BAD & & udpConnectivityState ! = UDP_NOT_AVAILABLE ) | | srcEndpoint - > type = = Endpoint : : TYPE_TCP_RELAY ) {
2017-03-30 16:06:59 +02:00
currentEndpoint = srcEndpoint ;
2018-05-15 20:23:46 +02:00
if ( srcEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY | | ( useTCP & & srcEndpoint - > type = = Endpoint : : TYPE_TCP_RELAY ) )
2017-03-30 16:06:59 +02:00
preferredRelay = srcEndpoint ;
}
2018-05-15 20:23:46 +02:00
LogDebugInfo ( ) ;
}
peerVersion = ( uint32_t ) in . ReadInt32 ( ) ;
LOGI ( " Peer version is %d " , peerVersion ) ;
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 ;
}
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
if ( flags & INIT_FLAG_DATA_SAVING_ENABLED ) {
dataSavingRequestedByPeer = true ;
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
}
if ( flags & INIT_FLAG_GROUP_CALLS_SUPPORTED ) {
peerCapabilities | = TGVOIP_PEER_CAP_GROUP_CALLS ;
}
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
unsigned int i ;
unsigned int numSupportedAudioCodecs = in . ReadByte ( ) ;
for ( i = 0 ; i < numSupportedAudioCodecs ; i + + ) {
if ( peerVersion < 5 )
2017-04-28 13:17:56 +02:00
in . ReadByte ( ) ; // ignore for now
2018-05-15 20:23:46 +02:00
else
in . ReadInt32 ( ) ;
}
unsigned int numSupportedVideoCodecs = in . ReadByte ( ) ;
for ( i = 0 ; i < numSupportedVideoCodecs ; i + + ) {
if ( peerVersion < 5 )
2017-04-28 13:17:56 +02:00
in . ReadByte ( ) ; // ignore for now
2018-05-15 20:23:46 +02:00
else
in . ReadInt32 ( ) ;
}
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
if ( buf ) {
BufferOutputStream out ( buf , outgoingPacketsBufferPool . GetSingleBufferSize ( ) ) ;
//WritePacketHeader(out, PKT_INIT_ACK, (peerVersion>=2 ? 10 : 2)+(peerVersion>=2 ? 6 : 4)*outgoingStreams.size());
out . WriteInt32 ( PROTOCOL_VERSION ) ;
out . WriteInt32 ( MIN_PROTOCOL_VERSION ) ;
out . WriteByte ( ( unsigned char ) outgoingStreams . size ( ) ) ;
for ( i = 0 ; i < outgoingStreams . size ( ) ; i + + ) {
out . WriteByte ( outgoingStreams [ i ] . id ) ;
out . WriteByte ( outgoingStreams [ i ] . type ) ;
if ( peerVersion < 5 )
out . WriteByte ( ( unsigned char ) ( outgoingStreams [ i ] . codec = = CODEC_OPUS ? CODEC_OPUS_OLD : 0 ) ) ;
else
out . WriteInt32 ( outgoingStreams [ i ] . codec ) ;
out . WriteInt16 ( outgoingStreams [ i ] . frameDuration ) ;
out . WriteByte ( ( unsigned char ) ( outgoingStreams [ i ] . enabled ? 1 : 0 ) ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
sendQueue - > Put ( PendingOutgoingPacket {
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_INIT_ACK ,
/*.len=*/ out . GetLength ( ) ,
/*.data=*/ buf ,
/*.endpoint=*/ NULL
} ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
if ( type = = PKT_INIT_ACK ) {
LOGD ( " Received init ack " ) ;
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
if ( ! receivedInitAck ) {
receivedInitAck = true ;
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
}
2018-05-15 20:23:46 +02:00
} else {
peerVersion = 1 ;
}
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
2018-05-15 20:23:46 +02:00
unsigned char streamCount = in . ReadByte ( ) ;
if ( streamCount = = 0 )
return ;
2017-02-02 17:24:40 +01:00
2018-05-15 20:23:46 +02:00
int i ;
Stream * incomingAudioStream = NULL ;
for ( i = 0 ; i < streamCount ; i + + ) {
Stream stm ;
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 ( ) ;
2017-03-30 16:06:59 +02:00
}
2018-05-15 20:23:46 +02:00
stm . frameDuration = ( uint16_t ) in . ReadInt16 ( ) ;
stm . enabled = in . ReadByte ( ) = = 1 ;
stm . jitterBuffer = new JitterBuffer ( NULL , stm . frameDuration ) ;
if ( stm . frameDuration > 50 )
stm . jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_60 " , 3 ) ) ;
else if ( stm . frameDuration > 30 )
stm . jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_40 " , 4 ) ) ;
else
stm . jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_20 " , 6 ) ) ;
stm . decoder = NULL ;
incomingStreams . push_back ( stm ) ;
if ( stm . type = = STREAM_TYPE_AUDIO & & ! incomingAudioStream )
incomingAudioStream = & stm ;
}
if ( ! incomingAudioStream )
return ;
2017-05-09 22:26:18 +02:00
2018-05-15 20:23:46 +02:00
if ( peerVersion > = 5 & & ! useMTProto2 ) {
useMTProto2 = true ;
LOGD ( " MTProto2 wasn't initially enabled for whatever reason but peer supports it; upgrading " ) ;
}
2017-02-02 17:24:40 +01:00
2018-05-25 21:14:45 +02:00
{
MutexGuard m ( audioIOMutex ) ;
if ( ! audioInput ) {
StartAudio ( ) ;
}
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
setEstablishedAt = GetCurrentTime ( ) + ServerConfig : : GetSharedInstance ( ) - > GetDouble ( " established_delay_if_no_stream_data " , 1.5 ) ;
if ( allowP2p )
SendPublicEndpointsRequest ( ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
if ( type = = PKT_STREAM_DATA | | type = = PKT_STREAM_DATA_X2 | | type = = PKT_STREAM_DATA_X3 ) {
if ( state ! = STATE_ESTABLISHED & & receivedInitAck )
SetState ( STATE_ESTABLISHED ) ;
int count ;
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 ;
}
int i ;
if ( srcEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY & & srcEndpoint ! = peerPreferredRelay ) {
peerPreferredRelay = srcEndpoint ;
}
for ( i = 0 ; i < count ; i + + ) {
unsigned char streamID = in . ReadByte ( ) ;
unsigned char flags = ( unsigned char ) ( streamID & 0xC0 ) ;
uint16_t sdlen = ( uint16_t ) ( flags & STREAM_DATA_FLAG_LEN16 ? in . ReadInt16 ( ) : in . ReadByte ( ) ) ;
uint32_t pts = ( uint32_t ) in . ReadInt32 ( ) ;
//LOGD("stream data, pts=%d, len=%d, rem=%d", pts, sdlen, in.Remaining());
audioTimestampIn = pts ;
if ( ! audioOutStarted & & audioOutput ) {
audioOutput - > Start ( ) ;
audioOutStarted = true ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( in . GetOffset ( ) + sdlen > len ) {
return ;
2017-04-09 18:14:33 +02:00
}
2018-05-15 20:23:46 +02:00
if ( incomingStreams . size ( ) > 0 & & incomingStreams [ 0 ] . jitterBuffer )
incomingStreams [ 0 ] . jitterBuffer - > HandleInput ( ( unsigned char * ) ( buffer + in . GetOffset ( ) ) , sdlen , pts ) ;
if ( i < count - 1 )
in . Seek ( in . GetOffset ( ) + sdlen ) ;
}
}
if ( type = = PKT_PING ) {
LOGD ( " Received ping from %s:%d " , packet . address - > ToString ( ) . c_str ( ) , srcEndpoint - > port ) ;
if ( srcEndpoint - > type ! = Endpoint : : TYPE_UDP_RELAY & & srcEndpoint - > type ! = Endpoint : : TYPE_TCP_RELAY & & ! allowP2p ) {
LOGW ( " Received p2p ping but p2p is disabled by manual override " ) ;
return ;
}
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
if ( ! buf ) {
LOGW ( " Dropping pong packet, queue overflow " ) ;
return ;
}
BufferOutputStream pkt ( buf , outgoingPacketsBufferPool . GetSingleBufferSize ( ) ) ;
pkt . WriteInt32 ( pseq ) ;
sendQueue - > Put ( PendingOutgoingPacket {
/*.seq=*/ GenerateOutSeq ( ) ,
/*.type=*/ PKT_PONG ,
/*.len=*/ pkt . GetLength ( ) ,
/*.data=*/ buf ,
/*.endpoint=*/ srcEndpoint ,
} ) ;
}
if ( type = = PKT_PONG ) {
if ( packetInnerLen > = 4 ) {
uint32_t pingSeq = ( uint32_t ) in . ReadInt32 ( ) ;
if ( pingSeq = = srcEndpoint - > lastPingSeq ) {
memmove ( & srcEndpoint - > rtts [ 1 ] , srcEndpoint - > rtts , sizeof ( double ) * 5 ) ;
srcEndpoint - > rtts [ 0 ] = GetCurrentTime ( ) - srcEndpoint - > lastPingTime ;
int i ;
srcEndpoint - > averageRTT = 0 ;
for ( i = 0 ; i < 6 ; i + + ) {
if ( srcEndpoint - > rtts [ i ] = = 0 )
break ;
srcEndpoint - > averageRTT + = srcEndpoint - > rtts [ i ] ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
srcEndpoint - > averageRTT / = i ;
LOGD ( " Current RTT via %s: %.3f, average: %.3f " , packet . address - > ToString ( ) . c_str ( ) , srcEndpoint - > rtts [ 0 ] , srcEndpoint - > averageRTT ) ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
}
if ( type = = PKT_STREAM_STATE ) {
unsigned char id = in . ReadByte ( ) ;
unsigned char enabled = in . ReadByte ( ) ;
unsigned int i ;
for ( i = 0 ; i < incomingStreams . size ( ) ; i + + ) {
if ( incomingStreams [ i ] . id = = id ) {
incomingStreams [ i ] . enabled = enabled = = 1 ;
UpdateAudioOutputState ( ) ;
break ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
}
if ( type = = PKT_LAN_ENDPOINT ) {
LOGV ( " received lan endpoint " ) ;
uint32_t peerAddr = ( uint32_t ) in . ReadInt32 ( ) ;
uint16_t peerPort = ( uint16_t ) in . ReadInt32 ( ) ;
MutexGuard m ( endpointsMutex ) ;
bool found = false ;
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
if ( ( * itrtr ) - > type = = Endpoint : : TYPE_UDP_P2P_LAN ) {
if ( currentEndpoint = = * itrtr )
currentEndpoint = preferredRelay ;
found = true ;
( * itrtr ) - > address = peerAddr ;
break ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
if ( ! found ) {
IPv4Address v4addr ( peerAddr ) ;
IPv6Address v6addr ( " ::0 " ) ;
unsigned char peerTag [ 16 ] ;
endpoints . push_back ( new Endpoint ( 0 , peerPort , v4addr , v6addr , Endpoint : : TYPE_UDP_P2P_LAN , peerTag ) ) ;
}
}
if ( type = = PKT_NETWORK_CHANGED & & currentEndpoint - > type ! = Endpoint : : TYPE_UDP_RELAY & & currentEndpoint - > type ! = Endpoint : : TYPE_TCP_RELAY ) {
currentEndpoint = preferredRelay ;
if ( allowP2p )
SendPublicEndpointsRequest ( ) ;
if ( peerVersion > = 2 ) {
uint32_t flags = ( uint32_t ) in . ReadInt32 ( ) ;
dataSavingRequestedByPeer = ( flags & INIT_FLAG_DATA_SAVING_ENABLED ) = = INIT_FLAG_DATA_SAVING_ENABLED ;
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
}
}
if ( type = = PKT_GROUP_CALL_KEY & & ! didReceiveGroupCallKey & & ! didSendGroupCallKey ) {
unsigned char groupKey [ 256 ] ;
in . ReadBytes ( groupKey , 256 ) ;
if ( callbacks . groupCallKeyReceived )
callbacks . groupCallKeyReceived ( this , groupKey ) ;
didReceiveGroupCallKey = true ;
}
if ( type = = PKT_REQUEST_GROUP & & ! didInvokeUpdateCallback ) {
if ( callbacks . upgradeToGroupCallRequested )
callbacks . upgradeToGroupCallRequested ( this ) ;
didInvokeUpdateCallback = true ;
}
}
void VoIPGroupController : : ProcessIncomingPacket ( NetworkPacket & packet , Endpoint * srcEndpoint ) {
//LOGD("Received incoming packet from %s:%u, %u bytes", packet.address->ToString().c_str(), packet.port, packet.length);
if ( packet . length < 17 | | packet . length > 2000 ) {
2018-05-24 18:42:28 +02:00
LOGW ( " Received packet has wrong length %d " , ( int ) packet . length ) ;
2018-05-15 20:23:46 +02:00
return ;
}
BufferOutputStream sigData ( packet . length ) ;
sigData . WriteBytes ( packet . data , packet . length - 16 ) ;
sigData . WriteBytes ( reflectorSelfSecret , 16 ) ;
unsigned char sig [ 32 ] ;
crypto . sha256 ( sigData . GetBuffer ( ) , sigData . GetLength ( ) , sig ) ;
if ( memcmp ( sig , packet . data + ( packet . length - 16 ) , 16 ) ! = 0 ) {
LOGW ( " Received packet has incorrect signature " ) ;
return ;
}
// reflector special response
if ( memcmp ( packet . data , reflectorSelfTagHash , 16 ) = = 0 & & packet . length > 60 ) {
//LOGI("possible reflector special response");
unsigned char firstBlock [ 16 ] ;
unsigned char iv [ 16 ] ;
memcpy ( iv , packet . data + 16 , 16 ) ;
unsigned char key [ 32 ] ;
crypto . sha256 ( reflectorSelfSecret , 16 , key ) ;
crypto . aes_cbc_decrypt ( packet . data + 32 , firstBlock , 16 , key , iv ) ;
BufferInputStream in ( firstBlock , 16 ) ;
in . Seek ( 8 ) ;
size_t len = ( size_t ) in . ReadInt32 ( ) ;
int32_t tlid = in . ReadInt32 ( ) ;
//LOGD("special response: len=%d, tlid=0x%08X", len, tlid);
if ( len % 4 = = 0 & & len + 60 < = packet . length & & packet . length < = 1500 ) {
lastRecvPacketTime = GetCurrentTime ( ) ;
memcpy ( iv , packet . data + 16 , 16 ) ;
unsigned char buf [ 1500 ] ;
crypto . aes_cbc_decrypt ( packet . data + 32 , buf , len + 16 , key , iv ) ;
try {
if ( tlid = = TLID_UDP_REFLECTOR_LAST_PACKETS_INFO ) {
MutexGuard m ( sentPacketsMutex ) ;
//LOGV("received udpReflector.lastPacketsInfo");
in = BufferInputStream ( buf , len + 16 ) ;
in . Seek ( 16 ) ;
/*int32_t date=*/ in . ReadInt32 ( ) ;
/*int64_t queryID=*/ in . ReadInt64 ( ) ;
int32_t vectorMagic = in . ReadInt32 ( ) ;
if ( vectorMagic ! = TLID_VECTOR ) {
LOGW ( " last packets info: expected vector, got %08X " , vectorMagic ) ;
return ;
}
int32_t recvCount = in . ReadInt32 ( ) ;
//LOGV("%d received packets", recvCount);
for ( int i = 0 ; i < recvCount ; i + + ) {
uint32_t p = ( uint32_t ) in . ReadInt32 ( ) ;
//LOGV("Relay received packet: %08X", p);
uint16_t id = ( uint16_t ) ( p & 0xFFFF ) ;
//LOGV("ack id %04X", id);
for ( std : : vector < PacketIdMapping > : : iterator pkt = recentSentPackets . begin ( ) ; pkt ! = recentSentPackets . end ( ) ; + + pkt ) {
//LOGV("== sent id %04X", pkt->id);
if ( pkt - > id = = id ) {
if ( ! pkt - > ackTime ) {
pkt - > ackTime = GetCurrentTime ( ) ;
conctl - > PacketAcknowledged ( pkt - > seq ) ;
//LOGV("relay acknowledged packet %u", pkt->seq);
if ( seqgt ( pkt - > seq , lastRemoteAckSeq ) )
lastRemoteAckSeq = pkt - > seq ;
}
break ;
}
}
}
vectorMagic = in . ReadInt32 ( ) ;
if ( vectorMagic ! = TLID_VECTOR ) {
LOGW ( " last packets info: expected vector, got %08X " , vectorMagic ) ;
return ;
}
int32_t sentCount = in . ReadInt32 ( ) ;
//LOGV("%d sent packets", sentCount);
for ( int i = 0 ; i < sentCount ; i + + ) {
/*int32_t p=*/ in . ReadInt32 ( ) ;
//LOGV("Sent packet: %08X", p);
}
if ( udpConnectivityState ! = UDP_AVAILABLE )
udpConnectivityState = UDP_AVAILABLE ;
if ( state ! = STATE_ESTABLISHED )
SetState ( STATE_ESTABLISHED ) ;
if ( ! audioInput ) {
StartAudio ( ) ;
if ( state ! = STATE_FAILED ) {
// audioOutput->Start();
}
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
} catch ( std : : out_of_range & x ) {
LOGE ( " Error parsing special response: %s " , x . what ( ) ) ;
2017-02-02 17:24:40 +01:00
}
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
}
if ( packet . length < 32 )
return ;
// it's a packet relayed from another participant - find the sender
MutexGuard m ( participantsMutex ) ;
GroupCallParticipant * sender = NULL ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( memcmp ( packet . data , p - > memberTagHash , 16 ) = = 0 ) {
//LOGV("received data packet from user %d", p->userID);
sender = & * p ;
break ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
}
if ( ! sender ) {
LOGV ( " Received data packet is from unknown user " ) ;
return ;
}
if ( memcmp ( packet . data + 16 , keyFingerprint , 8 ) ! = 0 ) {
LOGW ( " received packet has wrong key fingerprint " ) ;
return ;
}
BufferInputStream in ( packet . data , packet . length - 16 ) ;
in . Seek ( 16 + 8 ) ; // peer tag + key fingerprint
unsigned char msgKey [ 16 ] ;
in . ReadBytes ( msgKey , 16 ) ;
unsigned char decrypted [ 1500 ] ;
unsigned char aesKey [ 32 ] , aesIv [ 32 ] ;
KDF2 ( msgKey , 0 , aesKey , aesIv ) ;
size_t decryptedLen = in . Remaining ( ) - 16 ;
if ( decryptedLen > sizeof ( decrypted ) )
return ;
//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), decryptedLen-4);
uint8_t * decryptOffset = packet . data + in . GetOffset ( ) ;
if ( ( ( ( intptr_t ) decryptOffset ) % sizeof ( long ) ) ! = 0 ) {
LOGE ( " alignment2 packet.data+in.GetOffset() " ) ;
}
if ( decryptedLen % sizeof ( long ) ! = 0 ) {
LOGE ( " alignment2 decryptedLen " ) ;
}
crypto . aes_ige_decrypt ( packet . data + in . GetOffset ( ) , decrypted , decryptedLen , aesKey , aesIv ) ;
in = BufferInputStream ( decrypted , decryptedLen ) ;
//LOGD("received packet length: %d", in.ReadInt32());
BufferOutputStream buf ( decryptedLen + 32 ) ;
size_t x = 0 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( decrypted + 4 , decryptedLen - 4 ) ;
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
if ( memcmp ( msgKey , msgKeyLarge + 8 , 16 ) ! = 0 ) {
LOGW ( " Received packet from user %d has wrong hash " , sender - > userID ) ;
return ;
}
uint32_t innerLen = ( uint32_t ) in . ReadInt32 ( ) ;
if ( innerLen > decryptedLen - 4 ) {
2018-05-24 18:42:28 +02:00
LOGW ( " Received packet has wrong inner length (%d with total of %u) " , innerLen , ( unsigned int ) decryptedLen ) ;
2018-05-15 20:23:46 +02:00
return ;
}
if ( decryptedLen - innerLen < 12 ) {
2018-05-24 18:42:28 +02:00
LOGW ( " Received packet has too little padding (%u) " , ( unsigned int ) ( decryptedLen - innerLen ) ) ;
2018-05-15 20:23:46 +02:00
return ;
}
in = BufferInputStream ( decrypted + 4 , ( size_t ) innerLen ) ;
uint32_t tlid = ( uint32_t ) in . ReadInt32 ( ) ;
if ( tlid ! = TLID_DECRYPTED_AUDIO_BLOCK ) {
LOGW ( " Received packet has unknown TL ID 0x%08x " , tlid ) ;
return ;
}
in . Seek ( in . GetOffset ( ) + 16 ) ; // random bytes
int32_t flags = in . ReadInt32 ( ) ;
if ( ! ( flags & PFLAG_HAS_SEQ ) | | ! ( flags & PFLAG_HAS_SENDER_TAG_HASH ) ) {
LOGW ( " Received packet has wrong flags " ) ;
return ;
}
/*uint32_t seq=(uint32_t) */ in . ReadInt32 ( ) ;
unsigned char senderTagHash [ 16 ] ;
in . ReadBytes ( senderTagHash , 16 ) ;
if ( memcmp ( senderTagHash , sender - > memberTagHash , 16 ) ! = 0 ) {
LOGW ( " Received packet has wrong inner sender tag hash " ) ;
return ;
}
//int32_t oneMoreInnerLengthWhyDoWeEvenNeedThis;
if ( flags & PFLAG_HAS_DATA ) {
/*oneMoreInnerLengthWhyDoWeEvenNeedThis=*/ in . ReadTlLength ( ) ;
}
unsigned char type = ( unsigned char ) ( ( flags > > 24 ) & 0xFF ) ;
lastRecvPacketTime = GetCurrentTime ( ) ;
if ( type = = PKT_STREAM_DATA | | type = = PKT_STREAM_DATA_X2 | | type = = PKT_STREAM_DATA_X3 ) {
if ( state ! = STATE_ESTABLISHED & & receivedInitAck )
SetState ( STATE_ESTABLISHED ) ;
int count ;
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 ;
}
int i ;
//if(srcEndpoint->type==Endpoint::TYPE_UDP_RELAY && srcEndpoint!=peerPreferredRelay){
// peerPreferredRelay=srcEndpoint;
//}
for ( i = 0 ; i < count ; i + + ) {
unsigned char streamID = in . ReadByte ( ) ;
unsigned char sflags = ( unsigned char ) ( streamID & 0xC0 ) ;
uint16_t sdlen = ( uint16_t ) ( sflags & STREAM_DATA_FLAG_LEN16 ? in . ReadInt16 ( ) : in . ReadByte ( ) ) ;
uint32_t pts = ( uint32_t ) in . ReadInt32 ( ) ;
//LOGD("stream data, pts=%d, len=%d, rem=%d", pts, sdlen, in.Remaining());
audioTimestampIn = pts ;
/*if(!audioOutStarted && audioOutput){
audioOutput - > Start ( ) ;
audioOutStarted = true ;
} */
if ( in . GetOffset ( ) + sdlen > in . GetLength ( ) ) {
return ;
}
for ( std : : vector < Stream > : : iterator stm = sender - > streams . begin ( ) ; stm ! = sender - > streams . end ( ) ; + + stm ) {
if ( stm - > id = = streamID ) {
if ( stm - > jitterBuffer ) {
stm - > jitterBuffer - > HandleInput ( decrypted + 4 + in . GetOffset ( ) , sdlen , pts ) ;
}
2017-04-17 20:57:07 +02:00
break ;
}
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( i < count - 1 )
in . Seek ( in . GetOffset ( ) + sdlen ) ;
2017-02-02 17:24:40 +01:00
}
}
}
2018-05-15 20:23:46 +02:00
void VoIPGroupController : : SendUdpPing ( Endpoint * endpoint ) {
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
void VoIPController : : RunTickThread ( void * arg ) {
2017-02-02 17:24:40 +01:00
uint32_t tickCount = 0 ;
2017-04-28 13:17:56 +02:00
double startTime = GetCurrentTime ( ) ;
2017-02-02 17:24:40 +01:00
while ( runReceiver ) {
2017-04-17 20:57:07 +02:00
# ifndef _WIN32
2017-02-02 17:24:40 +01:00
usleep ( 100000 ) ;
2017-04-17 20:57:07 +02:00
# else
Sleep ( 100 ) ;
# endif
2017-09-07 07:39:33 +02:00
int prevSignalBarCount = GetSignalBarsCount ( ) ;
2017-08-21 18:02:37 +02:00
signalBarCount = 4 ;
2017-02-02 17:24:40 +01:00
tickCount + + ;
2017-07-03 03:42:49 +02:00
if ( connectionInitTime = = 0 )
continue ;
2017-06-06 03:44:16 +02:00
double time = GetCurrentTime ( ) ;
2017-08-21 18:02:37 +02:00
if ( state = = STATE_RECONNECTING )
signalBarCount = 1 ;
2017-07-03 03:42:49 +02:00
if ( tickCount % 5 = = 0 & & ( state = = STATE_ESTABLISHED | | state = = STATE_RECONNECTING ) ) {
2017-02-02 17:24:40 +01:00
memmove ( & rttHistory [ 1 ] , rttHistory , 31 * sizeof ( double ) ) ;
rttHistory [ 0 ] = GetAverageRTT ( ) ;
/*if(rttHistory[16]>0){
LOGI ( " rtt diff: %.3lf " , rttHistory [ 0 ] - rttHistory [ 16 ] ) ;
} */
int i ;
double v = 0 ;
for ( i = 1 ; i < 32 ; i + + ) {
v + = rttHistory [ i - 1 ] - rttHistory [ i ] ;
}
v = v / 32 ;
if ( rttHistory [ 0 ] > 10.0 & & rttHistory [ 8 ] > 10.0 & & ( networkType = = NET_TYPE_EDGE | | networkType = = NET_TYPE_GPRS ) ) {
waitingForAcks = true ;
2017-08-21 18:02:37 +02:00
signalBarCount = 1 ;
2017-02-02 17:24:40 +01:00
} else {
waitingForAcks = false ;
}
//LOGI("%.3lf/%.3lf, rtt diff %.3lf, waiting=%d, queue=%d", rttHistory[0], rttHistory[8], v, waitingForAcks, sendQueue->Size());
2018-05-15 20:23:46 +02:00
for ( std : : vector < 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 ;
}
2017-03-30 16:06:59 +02:00
}
2017-02-02 17:24:40 +01:00
}
if ( dontSendPackets > 0 )
dontSendPackets - - ;
2018-05-15 20:23:46 +02:00
unsigned int i ;
2017-02-02 17:24:40 +01:00
conctl - > Tick ( ) ;
2017-07-03 03:42:49 +02:00
if ( useTCP & & ! didAddTcpRelays ) {
std : : vector < Endpoint * > relays ;
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
2018-05-15 20:23:46 +02:00
if ( ( * itr ) - > type ! = Endpoint : : TYPE_UDP_RELAY )
2017-07-03 03:42:49 +02:00
continue ;
Endpoint * tcpRelay = new Endpoint ( * * itr ) ;
2018-05-15 20:23:46 +02:00
tcpRelay - > type = Endpoint : : TYPE_TCP_RELAY ;
2017-07-03 03:42:49 +02:00
tcpRelay - > averageRTT = 0 ;
tcpRelay - > lastPingSeq = 0 ;
tcpRelay - > lastPingTime = 0 ;
memset ( tcpRelay - > rtts , 0 , sizeof ( tcpRelay - > rtts ) ) ;
2018-05-15 20:23:46 +02:00
tcpRelay - > udpPongCount = 0 ;
if ( setCurrentEndpointToTCP & & currentEndpoint - > type ! = Endpoint : : TYPE_TCP_RELAY ) {
setCurrentEndpointToTCP = false ;
currentEndpoint = tcpRelay ;
preferredRelay = tcpRelay ;
}
2017-07-03 03:42:49 +02:00
relays . push_back ( tcpRelay ) ;
2017-06-06 03:44:16 +02:00
}
2017-07-03 03:42:49 +02:00
endpoints . insert ( endpoints . end ( ) , relays . begin ( ) , relays . end ( ) ) ;
didAddTcpRelays = true ;
2017-06-06 03:44:16 +02:00
}
2017-07-03 03:42:49 +02:00
if ( state = = STATE_ESTABLISHED & & encoder & & conctl ) {
2017-05-10 01:28:20 +02:00
if ( ( audioInput & & ! audioInput - > IsInitialized ( ) ) | | ( audioOutput & & ! audioOutput - > IsInitialized ( ) ) ) {
LOGE ( " Audio I/O failed " ) ;
2018-05-15 20:23:46 +02:00
lastError = ERROR_AUDIO_IO ;
2017-05-10 01:28:20 +02:00
SetState ( STATE_FAILED ) ;
}
2017-02-02 17:24:40 +01:00
int act = conctl - > GetBandwidthControlAction ( ) ;
if ( act = = TGVOIP_CONCTL_ACT_DECREASE ) {
uint32_t bitrate = encoder - > GetBitrate ( ) ;
if ( bitrate > 8000 )
2017-03-30 16:06:59 +02:00
encoder - > SetBitrate ( bitrate < ( minAudioBitrate + audioBitrateStepDecr ) ? minAudioBitrate : ( bitrate - audioBitrateStepDecr ) ) ;
2017-02-02 17:24:40 +01:00
} else if ( act = = TGVOIP_CONCTL_ACT_INCREASE ) {
uint32_t bitrate = encoder - > GetBitrate ( ) ;
if ( bitrate < maxBitrate )
2017-03-30 16:06:59 +02:00
encoder - > SetBitrate ( bitrate + audioBitrateStepIncr ) ;
2017-02-02 17:24:40 +01:00
}
if ( tickCount % 10 = = 0 & & encoder ) {
uint32_t sendLossCount = conctl - > GetSendLossCount ( ) ;
memmove ( sendLossCountHistory + 1 , sendLossCountHistory , 31 * sizeof ( uint32_t ) ) ;
sendLossCountHistory [ 0 ] = sendLossCount - prevSendLossCount ;
prevSendLossCount = sendLossCount ;
double avgSendLossCount = 0 ;
for ( i = 0 ; i < 10 ; i + + ) {
avgSendLossCount + = sendLossCountHistory [ i ] ;
}
2018-05-15 20:23:46 +02:00
double packetsPerSec = 1000 / ( double ) outgoingStreams [ 0 ] . frameDuration ;
2017-02-02 17:24:40 +01:00
avgSendLossCount = avgSendLossCount / 10 / packetsPerSec ;
//LOGV("avg send loss: %.1f%%", avgSendLossCount*100);
if ( avgSendLossCount > 0.1 ) {
encoder - > SetPacketLoss ( 40 ) ;
2018-05-15 20:23:46 +02:00
signalBarCount = 1 ;
2017-02-02 17:24:40 +01:00
} else if ( avgSendLossCount > 0.075 ) {
encoder - > SetPacketLoss ( 35 ) ;
2018-05-15 20:23:46 +02:00
signalBarCount = MIN ( signalBarCount , 2 ) ;
2017-02-02 17:24:40 +01:00
} else if ( avgSendLossCount > 0.0625 ) {
encoder - > SetPacketLoss ( 30 ) ;
2018-05-15 20:23:46 +02:00
signalBarCount = MIN ( signalBarCount , 2 ) ;
2017-02-02 17:24:40 +01:00
} else if ( avgSendLossCount > 0.05 ) {
encoder - > SetPacketLoss ( 25 ) ;
2018-05-15 20:23:46 +02:00
signalBarCount = MIN ( signalBarCount , 3 ) ;
2017-02-02 17:24:40 +01:00
} else if ( avgSendLossCount > 0.025 ) {
encoder - > SetPacketLoss ( 20 ) ;
2018-05-15 20:23:46 +02:00
signalBarCount = MIN ( signalBarCount , 3 ) ;
2017-02-02 17:24:40 +01:00
} else if ( avgSendLossCount > 0.01 ) {
encoder - > SetPacketLoss ( 17 ) ;
} else {
encoder - > SetPacketLoss ( 15 ) ;
}
2017-08-21 18:02:37 +02:00
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
if ( currentEndpoint - > type = = Endpoint : : TYPE_TCP_RELAY ) {
signalBarCount = MIN ( signalBarCount , 3 ) ;
}
2017-02-02 17:24:40 +01:00
bool areThereAnyEnabledStreams = false ;
for ( i = 0 ; i < outgoingStreams . size ( ) ; i + + ) {
2018-05-15 20:23:46 +02:00
if ( outgoingStreams [ i ] . enabled )
2017-02-02 17:24:40 +01:00
areThereAnyEnabledStreams = true ;
}
if ( ( waitingForAcks & & tickCount % 10 = = 0 ) | | ( ! areThereAnyEnabledStreams & & tickCount % 2 = = 0 ) ) {
2017-07-03 03:42:49 +02:00
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
if ( buf ) {
sendQueue - > Put ( PendingOutgoingPacket {
/*.seq=*/ ( firstSentPing = GenerateOutSeq ( ) ) ,
/*.type=*/ PKT_NOP ,
/*.len=*/ 0 ,
/*.data=*/ buf ,
/*.endpoint=*/ NULL
} ) ;
2017-02-02 17:24:40 +01:00
}
}
if ( state = = STATE_WAIT_INIT_ACK & & GetCurrentTime ( ) - stateChangeTime > .5 ) {
SendInit ( ) ;
}
if ( waitingForRelayPeerInfo & & GetCurrentTime ( ) - publicEndpointsReqTime > 5 ) {
LOGD ( " Resending peer relay info request " ) ;
SendPublicEndpointsRequest ( ) ;
}
2018-05-15 20:23:46 +02:00
{
MutexGuard m ( queuedPacketsMutex ) ;
for ( i = 0 ; i < queuedPackets . size ( ) ; i + + ) {
voip_queued_packet_t * qp = queuedPackets [ i ] ;
if ( qp - > timeout > 0 & & qp - > firstSentTime > 0 & & GetCurrentTime ( ) - qp - > firstSentTime > = qp - > timeout ) {
LOGD ( " Removing queued packet because of timeout " ) ;
if ( qp - > data )
free ( qp - > data ) ;
free ( qp ) ;
queuedPackets . erase ( queuedPackets . begin ( ) + i ) ;
i - - ;
continue ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( qp - > type = = PKT_GROUP_CALL_KEY & & didReceiveGroupCallKey ) {
LOGW ( " Not sending group call key packet because we already received one " ) ;
2017-06-06 03:44:16 +02:00
continue ;
2018-05-15 20:23:46 +02:00
}
if ( GetCurrentTime ( ) - qp - > lastSentTime > = qp - > retryInterval ) {
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
2017-07-03 03:42:49 +02:00
if ( buf ) {
2018-05-15 20:23:46 +02:00
uint32_t seq = GenerateOutSeq ( ) ;
memmove ( & qp - > seqs [ 1 ] , qp - > seqs , 4 * 9 ) ;
qp - > seqs [ 0 ] = seq ;
qp - > lastSentTime = GetCurrentTime ( ) ;
LOGD ( " Sending queued packet, seq=%u, type=%u, len=%u " , seq , qp - > type , unsigned ( qp - > length ) ) ;
if ( qp - > firstSentTime = = 0 )
qp - > firstSentTime = qp - > lastSentTime ;
if ( qp - > length )
memcpy ( buf , qp - > data , qp - > length ) ;
2017-07-03 03:42:49 +02:00
sendQueue - > Put ( PendingOutgoingPacket {
2018-05-15 20:23:46 +02:00
/*.seq=*/ seq ,
/*.type=*/ qp - > type ,
/*.len=*/ qp - > length ,
2017-07-03 03:42:49 +02:00
/*.data=*/ buf ,
2018-05-15 20:23:46 +02:00
/*.endpoint=*/ NULL
2017-07-03 03:42:49 +02:00
} ) ;
}
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
}
for ( std : : vector < Stream > : : iterator stm = incomingStreams . begin ( ) ; stm ! = incomingStreams . end ( ) ; + + stm ) {
if ( stm - > jitterBuffer ) {
stm - > jitterBuffer - > Tick ( ) ;
//double avgDelay=stm->jitterBuffer->GetAverageDelay();
double avgLateCount [ 3 ] ;
stm - > jitterBuffer - > GetAverageLateCount ( avgLateCount ) ;
/*if(avgDelay>=5)
signalBarCount = 1 ;
else if ( avgDelay > = 4 )
signalBarCount = MIN ( signalBarCount , 2 ) ;
else if ( avgDelay > = 3 )
signalBarCount = MIN ( signalBarCount , 3 ) ; */
if ( avgLateCount [ 2 ] > = 0.2 )
signalBarCount = 1 ;
else if ( avgLateCount [ 2 ] > = 0.1 )
signalBarCount = MIN ( signalBarCount , 2 ) ;
2017-02-02 17:24:40 +01:00
}
}
2018-05-15 20:23:46 +02:00
{
MutexGuard m ( endpointsMutex ) ;
SendRelayPings ( ) ;
if ( udpConnectivityState = = UDP_UNKNOWN ) {
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
if ( ( * itr ) - > type = = Endpoint : : TYPE_UDP_RELAY ) {
SendUdpPing ( * itr ) ;
}
2017-07-03 03:42:49 +02:00
}
2018-05-15 20:23:46 +02:00
udpConnectivityState = UDP_PING_SENT ;
lastUdpPingTime = time ;
udpPingCount = 1 ;
} else if ( udpConnectivityState = = UDP_PING_SENT | | udpConnectivityState = = UDP_BAD ) {
int targetPingCount = udpConnectivityState = = UDP_BAD ? 10 : 4 ;
if ( time - lastUdpPingTime > = ( udpPingCount < targetPingCount ? 0.5 : 1.0 ) ) {
if ( udpPingCount < targetPingCount ) {
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
if ( ( * itr ) - > type = = Endpoint : : TYPE_UDP_RELAY ) {
SendUdpPing ( * itr ) ;
}
2017-07-03 03:42:49 +02:00
}
2018-05-15 20:23:46 +02:00
udpPingCount + + ;
lastUdpPingTime = time ;
} else {
double avgPongs = 0 ;
int count = 0 ;
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
if ( ( * itr ) - > type = = Endpoint : : TYPE_UDP_RELAY ) {
if ( ( * itr ) - > udpPongCount > 0 ) {
avgPongs + = ( double ) ( * itr ) - > udpPongCount ;
count + + ;
}
}
}
if ( count > 0 )
avgPongs / = ( double ) count ;
else
avgPongs = 0.0 ;
LOGI ( " UDP ping reply count: %.2f " , avgPongs ) ;
bool configUseTCP = ServerConfig : : GetSharedInstance ( ) - > GetBoolean ( " use_tcp " , true ) ;
if ( configUseTCP ) {
if ( avgPongs = = 0.0 | | ( udpConnectivityState = = UDP_BAD & & avgPongs < 7.0 ) ) {
udpConnectivityState = UDP_NOT_AVAILABLE ;
useTCP = true ;
useUDP = false ;
waitingForRelayPeerInfo = false ;
if ( currentEndpoint - > type ! = Endpoint : : TYPE_TCP_RELAY )
setCurrentEndpointToTCP = true ;
} else if ( avgPongs < 3.0 ) {
udpConnectivityState = UDP_BAD ;
useTCP = true ;
setCurrentEndpointToTCP = true ;
} else {
udpConnectivityState = UDP_AVAILABLE ;
}
} else {
udpConnectivityState = UDP_NOT_AVAILABLE ;
}
//LOGW("No UDP ping replies received; assuming no connectivity and trying TCP")
//udpConnectivityState=UDP_NOT_AVAILABLE;
//useTCP=true;
2017-07-03 03:42:49 +02:00
}
}
}
}
2017-02-02 17:24:40 +01:00
2017-07-03 03:42:49 +02:00
if ( state = = STATE_ESTABLISHED | | state = = STATE_RECONNECTING ) {
if ( time - lastRecvPacketTime > = config . recv_timeout ) {
2018-05-15 20:23:46 +02:00
if ( currentEndpoint & & currentEndpoint - > type ! = Endpoint : : TYPE_UDP_RELAY & & currentEndpoint - > type ! = Endpoint : : TYPE_TCP_RELAY ) {
2017-02-02 17:24:40 +01:00
LOGW ( " Packet receive timeout, switching to relay " ) ;
2017-03-30 16:06:59 +02:00
currentEndpoint = preferredRelay ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
Endpoint * e = * itrtr ;
2018-05-15 20:23:46 +02:00
if ( e - > type = = Endpoint : : TYPE_UDP_P2P_INET | | e - > type = = Endpoint : : TYPE_UDP_P2P_LAN ) {
2017-04-17 20:57:07 +02:00
e - > averageRTT = 0 ;
memset ( e - > rtts , 0 , sizeof ( e - > rtts ) ) ;
2017-03-30 16:06:59 +02:00
}
}
2017-02-02 17:24:40 +01:00
if ( allowP2p ) {
SendPublicEndpointsRequest ( ) ;
}
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
2017-04-28 13:17:56 +02:00
BufferOutputStream s ( 4 ) ;
2017-02-02 17:24:40 +01:00
s . WriteInt32 ( dataSavingMode ? INIT_FLAG_DATA_SAVING_ENABLED : 0 ) ;
SendPacketReliably ( PKT_NETWORK_CHANGED , s . GetBuffer ( ) , s . GetLength ( ) , 1 , 20 ) ;
2017-07-03 03:42:49 +02:00
lastRecvPacketTime = time ;
2017-02-02 17:24:40 +01:00
} else {
LOGW ( " Packet receive timeout, disconnecting " ) ;
2018-05-15 20:23:46 +02:00
lastError = ERROR_TIMEOUT ;
2017-02-02 17:24:40 +01:00
SetState ( STATE_FAILED ) ;
}
}
2017-04-28 13:17:56 +02:00
} else if ( state = = STATE_WAIT_INIT | | state = = STATE_WAIT_INIT_ACK ) {
2017-02-02 17:24:40 +01:00
if ( GetCurrentTime ( ) - connectionInitTime > = config . init_timeout ) {
LOGW ( " Init timeout, disconnecting " ) ;
2018-05-15 20:23:46 +02:00
lastError = ERROR_TIMEOUT ;
2017-02-02 17:24:40 +01:00
SetState ( STATE_FAILED ) ;
}
}
2017-04-28 13:17:56 +02:00
2017-07-03 03:42:49 +02:00
if ( state = = STATE_ESTABLISHED & & time - lastRecvPacketTime > = reconnectingTimeout ) {
SetState ( STATE_RECONNECTING ) ;
}
if ( state ! = STATE_ESTABLISHED & & setEstablishedAt > 0 & & time > = setEstablishedAt ) {
SetState ( STATE_ESTABLISHED ) ;
setEstablishedAt = 0 ;
}
2018-05-15 20:23:46 +02:00
if ( tickCount % 10 = = 0 ) {
signalBarsHistory [ ( tickCount / 10 ) % sizeof ( signalBarsHistory ) ] = ( unsigned char ) signalBarCount ;
//LOGV("Signal bar count history %08X", *reinterpret_cast<uint32_t *>(&signalBarsHistory));
int _signalBarCount = GetSignalBarsCount ( ) ;
if ( _signalBarCount ! = prevSignalBarCount ) {
LOGD ( " SIGNAL BAR COUNT CHANGED: %d " , _signalBarCount ) ;
if ( callbacks . signalBarCountChanged )
callbacks . signalBarCountChanged ( this , _signalBarCount ) ;
}
2017-08-21 18:02:37 +02:00
}
2017-07-03 03:42:49 +02:00
2018-05-15 20:23:46 +02:00
if ( statsDump & & incomingStreams . size ( ) = = 1 ) {
JitterBuffer * jitterBuffer = incomingStreams [ 0 ] . jitterBuffer ;
2017-04-28 13:17:56 +02: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 " ,
GetCurrentTime ( ) - startTime ,
currentEndpoint - > rtts [ 0 ] ,
lastRemoteSeq ,
seq ,
lastRemoteAckSeq ,
recvLossCount ,
conctl ? conctl - > GetSendLossCount ( ) : 0 ,
2017-04-19 15:39:27 +02:00
conctl ? ( int ) conctl - > GetInflightDataSize ( ) : 0 ,
2017-04-28 13:17:56 +02:00
encoder ? encoder - > GetBitrate ( ) : 0 ,
encoder ? encoder - > GetPacketLoss ( ) : 0 ,
jitterBuffer ? jitterBuffer - > GetLastMeasuredJitter ( ) : 0 ,
jitterBuffer ? jitterBuffer - > GetLastMeasuredDelay ( ) * 0.06 : 0 ,
2017-05-21 16:50:23 +02:00
jitterBuffer ? jitterBuffer - > GetAverageDelay ( ) * 0.06 : 0 ) ;
2017-04-28 13:17:56 +02:00
}
2017-05-09 22:26:18 +02:00
2017-02-02 17:24:40 +01:00
}
LOGI ( " === tick thread exiting === " ) ;
}
2017-04-17 20:57:07 +02:00
Endpoint & VoIPController : : GetRemoteEndpoint ( ) {
return * currentEndpoint ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
void VoIPController : : SendPacket ( unsigned char * data , size_t len , Endpoint * ep , PendingOutgoingPacket & srcPacket ) {
2017-02-02 17:24:40 +01:00
if ( stopping )
return ;
2018-05-15 20:23:46 +02:00
if ( ep - > type = = Endpoint : : TYPE_TCP_RELAY & & ! useTCP )
2017-06-06 03:44:16 +02:00
return ;
2017-04-28 13:17:56 +02:00
BufferOutputStream out ( len + 128 ) ;
2018-05-15 20:23:46 +02:00
if ( ep - > type = = Endpoint : : TYPE_UDP_RELAY | | ep - > type = = Endpoint : : TYPE_TCP_RELAY )
2017-04-17 20:57:07 +02:00
out . WriteBytes ( ( unsigned char * ) ep - > peerTag , 16 ) ;
2017-02-02 17:24:40 +01:00
else
out . WriteBytes ( callID , 16 ) ;
if ( len > 0 ) {
2018-05-15 20:23:46 +02:00
if ( useMTProto2 ) {
BufferOutputStream inner ( len + 128 ) ;
inner . WriteInt32 ( ( uint32_t ) len ) ;
inner . WriteBytes ( data , len ) ;
2017-02-02 17:24:40 +01:00
size_t padLen = 16 - inner . GetLength ( ) % 16 ;
2018-05-15 20:23:46 +02:00
if ( padLen < 12 )
padLen + = 16 ;
unsigned char padding [ 28 ] ;
2017-02-02 17:24:40 +01:00
crypto . rand_bytes ( ( uint8_t * ) padding , padLen ) ;
inner . WriteBytes ( padding , padLen ) ;
2018-05-15 20:23:46 +02:00
assert ( inner . GetLength ( ) % 16 = = 0 ) ;
unsigned char key [ 32 ] , iv [ 32 ] , msgKey [ 16 ] ;
out . WriteBytes ( keyFingerprint , 8 ) ;
BufferOutputStream buf ( len + 32 ) ;
size_t x = isOutgoing ? 0 : 8 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( inner . GetBuffer ( ) + 4 , inner . GetLength ( ) - 4 ) ;
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
memcpy ( msgKey , msgKeyLarge + 8 , 16 ) ;
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 ( ) ) ;
} else {
BufferOutputStream inner ( len + 128 ) ;
inner . WriteInt32 ( len ) ;
inner . WriteBytes ( data , len ) ;
if ( inner . GetLength ( ) % 16 ! = 0 ) {
size_t padLen = 16 - inner . GetLength ( ) % 16 ;
unsigned char padding [ 16 ] ;
crypto . rand_bytes ( ( uint8_t * ) padding , padLen ) ;
inner . WriteBytes ( padding , padLen ) ;
}
assert ( inner . GetLength ( ) % 16 = = 0 ) ;
unsigned char key [ 32 ] , iv [ 32 ] , msgHash [ SHA1_LENGTH ] ;
crypto . sha1 ( ( uint8_t * ) inner . GetBuffer ( ) , len + 4 , msgHash ) ;
out . WriteBytes ( keyFingerprint , 8 ) ;
out . WriteBytes ( ( msgHash + ( SHA1_LENGTH - 16 ) ) , 16 ) ;
KDF ( msgHash + ( SHA1_LENGTH - 16 ) , isOutgoing ? 0 : 8 , key , iv ) ;
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
}
}
2017-04-17 20:57:07 +02:00
//LOGV("Sending %d bytes to %s:%d", out.GetLength(), ep->address.ToString().c_str(), ep->port);
2018-05-15 20:23:46 +02:00
NetworkPacket pkt = { 0 } ;
2017-04-17 20:57:07 +02:00
pkt . address = ( NetworkAddress * ) & ep - > address ;
pkt . port = ep - > port ;
pkt . length = out . GetLength ( ) ;
pkt . data = out . GetBuffer ( ) ;
2018-05-15 20:23:46 +02:00
pkt . protocol = ep - > type = = Endpoint : : TYPE_TCP_RELAY ? PROTO_TCP : PROTO_UDP ;
ActuallySendPacket ( pkt , ep ) ;
}
void VoIPController : : ActuallySendPacket ( NetworkPacket & pkt , Endpoint * ep ) {
//LOGI("Sending packet of %d bytes", pkt.length);
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesSentMobile + = ( uint64_t ) pkt . length ;
else
stats . bytesSentWifi + = ( uint64_t ) pkt . length ;
if ( ep - > type = = Endpoint : : TYPE_TCP_RELAY ) {
if ( ep - > socket & & ! ep - > socket - > IsFailed ( ) ) {
2017-07-03 03:42:49 +02:00
ep - > socket - > Send ( & pkt ) ;
} else {
2018-05-15 20:23:46 +02:00
if ( ep - > socket ) {
LOGD ( " closing failed TCP socket: %s:%u " , ep - > address . ToString ( ) . c_str ( ) , ep - > port ) ;
ep - > socket - > Close ( ) ;
delete ep - > socket ;
ep - > socket = NULL ;
}
2017-07-03 03:42:49 +02:00
LOGI ( " connecting to tcp: %s:%u " , ep - > address . ToString ( ) . c_str ( ) , ep - > port ) ;
NetworkSocket * s ;
if ( proxyProtocol = = PROXY_NONE ) {
s = NetworkSocket : : Create ( PROTO_TCP ) ;
} else if ( proxyProtocol = = PROXY_SOCKS5 ) {
NetworkSocket * rawTcp = NetworkSocket : : Create ( PROTO_TCP ) ;
openingTcpSocket = rawTcp ;
rawTcp - > Connect ( resolvedProxyAddress , proxyPort ) ;
if ( rawTcp - > IsFailed ( ) ) {
openingTcpSocket = NULL ;
rawTcp - > Close ( ) ;
delete rawTcp ;
LOGW ( " Error connecting to SOCKS5 proxy " ) ;
return ;
}
NetworkSocketSOCKS5Proxy * proxy = new NetworkSocketSOCKS5Proxy ( rawTcp , NULL , proxyUsername , proxyPassword ) ;
2018-05-10 14:33:14 +02:00
openingTcpSocket = proxy ;
2017-07-03 03:42:49 +02:00
proxy - > InitConnection ( ) ;
if ( proxy - > IsFailed ( ) ) {
openingTcpSocket = NULL ;
LOGW ( " Proxy initialization failed " ) ;
proxy - > Close ( ) ;
delete proxy ;
return ;
}
s = proxy ;
2017-07-04 02:04:59 +02:00
} /*else if(proxyProtocol==PROXY_HTTP){
2017-07-03 03:42:49 +02:00
s = NetworkSocket : : Create ( PROTO_TCP ) ;
2017-07-04 02:04:59 +02:00
} */ else {
2017-07-03 03:42:49 +02:00
LOGE ( " Unsupported proxy protocol %d " , proxyProtocol ) ;
SetState ( STATE_FAILED ) ;
return ;
}
s - > Connect ( & ep - > address , ep - > port ) ;
if ( s - > IsFailed ( ) ) {
2018-05-10 14:33:14 +02:00
openingTcpSocket = NULL ;
2017-07-03 03:42:49 +02:00
s - > Close ( ) ;
delete s ;
LOGW ( " Error connecting to %s:%u " , ep - > address . ToString ( ) . c_str ( ) , ep - > port ) ;
} else {
NetworkSocketTCPObfuscated * tcpWrapper = new NetworkSocketTCPObfuscated ( s ) ;
openingTcpSocket = tcpWrapper ;
tcpWrapper - > InitConnection ( ) ;
openingTcpSocket = NULL ;
if ( tcpWrapper - > IsFailed ( ) ) {
tcpWrapper - > Close ( ) ;
delete tcpWrapper ;
LOGW ( " Error initializing connection to %s:%u " , ep - > address . ToString ( ) . c_str ( ) , ep - > port ) ;
} else {
tcpWrapper - > Send ( & pkt ) ;
ep - > socket = tcpWrapper ;
selectCanceller - > CancelSelect ( ) ;
}
}
}
} else {
udpSocket - > Send ( & pkt ) ;
}
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SetNetworkType ( int type ) {
2017-02-02 17:24:40 +01:00
networkType = type ;
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
2017-07-03 03:42:49 +02:00
std : : string itfName = udpSocket - > GetLocalInterfaceInfo ( NULL , NULL ) ;
2017-04-17 20:57:07 +02:00
if ( itfName ! = activeNetItfName ) {
2017-07-03 03:42:49 +02:00
udpSocket - > OnActiveInterfaceChanged ( ) ;
2017-04-17 20:57:07 +02:00
LOGI ( " Active network interface changed: %s -> %s " , activeNetItfName . c_str ( ) , itfName . c_str ( ) ) ;
bool isFirstChange = activeNetItfName . length ( ) = = 0 ;
activeNetItfName = itfName ;
2017-02-02 17:24:40 +01:00
if ( isFirstChange )
return ;
2018-05-15 20:23:46 +02:00
if ( currentEndpoint & & currentEndpoint - > type ! = Endpoint : : TYPE_UDP_RELAY ) {
if ( preferredRelay - > type = = Endpoint : : TYPE_UDP_RELAY )
2017-06-06 03:44:16 +02:00
currentEndpoint = preferredRelay ;
2018-05-15 20:23:46 +02:00
MutexGuard m ( endpointsMutex ) ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; ) {
Endpoint * endpoint = * itr ;
2018-05-15 20:23:46 +02:00
if ( endpoint - > type = = Endpoint : : TYPE_UDP_RELAY & & useTCP ) {
2017-06-06 03:44:16 +02:00
useTCP = false ;
2018-05-15 20:23:46 +02:00
if ( preferredRelay - > type = = Endpoint : : TYPE_TCP_RELAY ) {
2017-06-06 03:44:16 +02:00
preferredRelay = endpoint ;
currentEndpoint = endpoint ;
}
2018-05-15 20:23:46 +02:00
} else if ( endpoint - > type = = Endpoint : : TYPE_TCP_RELAY & & endpoint - > socket ) {
2017-07-03 03:42:49 +02:00
endpoint - > socket - > Close ( ) ;
2017-06-06 03:44:16 +02:00
}
2018-05-15 20:23:46 +02:00
//if(endpoint->type==Endpoint::TYPE_UDP_P2P_INET){
2017-04-17 20:57:07 +02:00
endpoint - > averageRTT = 0 ;
memset ( endpoint - > rtts , 0 , sizeof ( endpoint - > rtts ) ) ;
2017-06-06 03:44:16 +02:00
//}
2018-05-15 20:23:46 +02:00
if ( endpoint - > type = = Endpoint : : TYPE_UDP_P2P_LAN ) {
2017-04-17 20:57:07 +02:00
delete endpoint ;
2017-03-30 16:06:59 +02:00
itr = endpoints . erase ( itr ) ;
} else {
+ + itr ;
2017-02-02 17:24:40 +01:00
}
}
}
2017-07-03 03:42:49 +02:00
udpConnectivityState = UDP_UNKNOWN ;
udpPingCount = 0 ;
lastUdpPingTime = 0 ;
if ( proxyProtocol = = PROXY_SOCKS5 )
InitUDPProxy ( ) ;
2017-02-02 17:24:40 +01:00
if ( allowP2p & & currentEndpoint ) {
SendPublicEndpointsRequest ( ) ;
}
2017-04-28 13:17:56 +02:00
BufferOutputStream s ( 4 ) ;
2017-02-02 17:24:40 +01:00
s . WriteInt32 ( dataSavingMode ? INIT_FLAG_DATA_SAVING_ENABLED : 0 ) ;
SendPacketReliably ( PKT_NETWORK_CHANGED , s . GetBuffer ( ) , s . GetLength ( ) , 1 , 20 ) ;
2017-07-03 03:42:49 +02:00
selectCanceller - > CancelSelect ( ) ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
LOGI ( " set network type: %d, active interface %s " , type , activeNetItfName . c_str ( ) ) ;
2018-05-15 20:23:46 +02:00
}
void VoIPGroupController : : SetNetworkType ( int type ) {
networkType = type ;
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
std : : string itfName = udpSocket - > GetLocalInterfaceInfo ( NULL , NULL ) ;
if ( itfName ! = activeNetItfName ) {
udpSocket - > OnActiveInterfaceChanged ( ) ;
LOGI ( " Active network interface changed: %s -> %s " , activeNetItfName . c_str ( ) , itfName . c_str ( ) ) ;
bool isFirstChange = activeNetItfName . length ( ) = = 0 ;
activeNetItfName = itfName ;
if ( isFirstChange )
return ;
udpConnectivityState = UDP_UNKNOWN ;
udpPingCount = 0 ;
lastUdpPingTime = 0 ;
if ( proxyProtocol = = PROXY_SOCKS5 )
InitUDPProxy ( ) ;
selectCanceller - > CancelSelect ( ) ;
}
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
double VoIPController : : GetAverageRTT ( ) {
2017-02-02 17:24:40 +01:00
if ( lastSentSeq > = lastRemoteAckSeq ) {
uint32_t diff = lastSentSeq - lastRemoteAckSeq ;
//LOGV("rtt diff=%u", diff);
if ( diff < 32 ) {
double res = 0 ;
int count = 0 ;
2018-05-15 20:23:46 +02:00
/*for(i=diff;i<32;i++){
2017-02-02 17:24:40 +01:00
if ( remoteAcks [ i - diff ] > 0 ) {
res + = ( remoteAcks [ i - diff ] - sentPacketTimes [ i ] ) ;
count + + ;
}
2018-05-15 20:23:46 +02:00
} */
2018-05-28 01:17:22 +02:00
MutexGuard m ( queuedPacketsMutex ) ;
2018-05-15 20:23:46 +02:00
for ( std : : vector < RecentOutgoingPacket > : : iterator itr = recentOutgoingPackets . begin ( ) ; itr ! = recentOutgoingPackets . end ( ) ; + + itr ) {
if ( itr - > ackTime > 0 ) {
res + = ( itr - > ackTime - itr - > sendTime ) ;
count + + ;
}
2017-02-02 17:24:40 +01:00
}
if ( count > 0 )
res / = count ;
return res ;
}
}
return 999 ;
}
2017-03-30 16:06:59 +02:00
# if defined(__APPLE__)
static void initMachTimestart ( ) {
mach_timebase_info_data_t tb = { 0 , 0 } ;
mach_timebase_info ( & tb ) ;
2017-04-17 20:57:07 +02:00
VoIPController : : machTimebase = tb . numer ;
VoIPController : : machTimebase / = tb . denom ;
VoIPController : : machTimestart = mach_absolute_time ( ) ;
2017-03-30 16:06:59 +02:00
}
# endif
2017-04-17 20:57:07 +02:00
double VoIPController : : GetCurrentTime ( ) {
2017-02-02 17:24:40 +01:00
# if defined(__linux__)
struct timespec ts ;
clock_gettime ( CLOCK_MONOTONIC , & ts ) ;
return ts . tv_sec + ( double ) ts . tv_nsec / 1000000000.0 ;
# elif defined(__APPLE__)
2017-03-30 16:06:59 +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)
if ( ! didInitWin32TimeScale ) {
LARGE_INTEGER scale ;
QueryPerformanceFrequency ( & scale ) ;
win32TimeScale = scale . QuadPart ;
didInitWin32TimeScale = true ;
}
LARGE_INTEGER t ;
QueryPerformanceCounter ( & t ) ;
return ( double ) t . QuadPart / ( double ) win32TimeScale ;
2017-02-02 17:24:40 +01:00
# endif
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SetState ( int state ) {
2017-02-02 17:24:40 +01:00
this - > state = state ;
2017-04-28 13:17:56 +02:00
LOGV ( " Call state changed to %d " , state ) ;
2017-02-02 17:24:40 +01:00
stateChangeTime = GetCurrentTime ( ) ;
2018-05-15 20:23:46 +02:00
if ( callbacks . connectionStateChanged ) {
callbacks . connectionStateChanged ( this , state ) ;
2017-02-02 17:24:40 +01:00
}
2018-05-15 20:23:46 +02:00
if ( state = = STATE_ESTABLISHED )
SetMicMute ( micMuted ) ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SetMicMute ( bool mute ) {
2017-02-02 17:24:40 +01:00
micMuted = mute ;
if ( audioInput ) {
if ( mute )
audioInput - > Stop ( ) ;
else
audioInput - > Start ( ) ;
2017-03-30 16:06:59 +02:00
if ( ! audioInput - > IsInitialized ( ) ) {
2018-05-15 20:23:46 +02:00
lastError = ERROR_AUDIO_IO ;
2017-03-30 16:06:59 +02:00
SetState ( STATE_FAILED ) ;
return ;
}
2017-02-02 17:24:40 +01:00
}
if ( echoCanceller )
echoCanceller - > Enable ( ! mute ) ;
2018-05-15 20:23:46 +02:00
if ( state = = STATE_ESTABLISHED ) {
unsigned int i ;
for ( i = 0 ; i < outgoingStreams . size ( ) ; i + + ) {
if ( outgoingStreams [ i ] . type = = STREAM_TYPE_AUDIO ) {
unsigned char buf [ 2 ] ;
buf [ 0 ] = outgoingStreams [ i ] . id ;
buf [ 1 ] = ( char ) ( mute ? 0 : 1 ) ;
SendPacketReliably ( PKT_STREAM_STATE , buf , 2 , .5f , 20 ) ;
outgoingStreams [ i ] . enabled = ! mute ;
}
2017-02-02 17:24:40 +01:00
}
}
}
2017-04-17 20:57:07 +02:00
void VoIPController : : UpdateAudioOutputState ( ) {
2017-02-02 17:24:40 +01:00
bool areAnyAudioStreamsEnabled = false ;
2018-05-15 20:23:46 +02:00
unsigned int i ;
2017-02-02 17:24:40 +01:00
for ( i = 0 ; i < incomingStreams . size ( ) ; i + + ) {
2018-05-15 20:23:46 +02:00
if ( incomingStreams [ i ] . type = = STREAM_TYPE_AUDIO & & incomingStreams [ i ] . enabled )
2017-02-02 17:24:40 +01:00
areAnyAudioStreamsEnabled = true ;
}
2018-05-15 20:23:46 +02:00
/*if(jitterBuffer){
2017-02-02 17:24:40 +01:00
jitterBuffer - > Reset ( ) ;
}
if ( decoder ) {
decoder - > ResetQueue ( ) ;
2018-05-15 20:23:46 +02:00
} */
2017-02-02 17:24:40 +01:00
if ( audioOutput ) {
if ( audioOutput - > IsPlaying ( ) ! = areAnyAudioStreamsEnabled ) {
if ( areAnyAudioStreamsEnabled )
audioOutput - > Start ( ) ;
else
audioOutput - > Stop ( ) ;
}
}
}
2017-04-17 20:57:07 +02: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 ) ;
2017-02-02 17:24:40 +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 ( ) ;
buf . WriteBytes ( encryptionKey + 32 + x , 16 ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( msgKey , 16 ) ;
2017-02-02 17:24:40 +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 ( ) ;
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 ) ;
2017-02-02 17:24:40 +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 ) ;
buf . WriteBytes ( sB + 8 , 12 ) ;
buf . WriteBytes ( sC + 4 , 12 ) ;
2017-02-02 17:24:40 +01:00
assert ( buf . GetLength ( ) = = 32 ) ;
memcpy ( aesKey , buf . GetBuffer ( ) , 32 ) ;
buf . Reset ( ) ;
2017-03-30 16:06:59 +02:00
buf . WriteBytes ( sA + 8 , 12 ) ;
buf . WriteBytes ( sB , 8 ) ;
buf . WriteBytes ( sC + 16 , 4 ) ;
buf . WriteBytes ( sD , 8 ) ;
2017-02-02 17:24:40 +01:00
assert ( buf . GetLength ( ) = = 32 ) ;
memcpy ( aesIv , buf . GetBuffer ( ) , 32 ) ;
}
2018-05-15 20:23:46 +02:00
void VoIPController : : KDF2 ( unsigned char * msgKey , size_t x , unsigned char * aesKey , unsigned char * aesIv ) {
uint8_t sA [ 32 ] , sB [ 32 ] ;
BufferOutputStream buf ( 128 ) ;
buf . WriteBytes ( msgKey , 16 ) ;
buf . WriteBytes ( encryptionKey + x , 36 ) ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sA ) ;
buf . Reset ( ) ;
buf . WriteBytes ( encryptionKey + 40 + x , 36 ) ;
buf . WriteBytes ( msgKey , 16 ) ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , sB ) ;
buf . Reset ( ) ;
buf . WriteBytes ( sA , 8 ) ;
buf . WriteBytes ( sB + 8 , 16 ) ;
buf . WriteBytes ( sA + 24 , 8 ) ;
memcpy ( aesKey , buf . GetBuffer ( ) , 32 ) ;
buf . Reset ( ) ;
buf . WriteBytes ( sB , 8 ) ;
buf . WriteBytes ( sA + 8 , 16 ) ;
buf . WriteBytes ( sB + 24 , 8 ) ;
memcpy ( aesIv , buf . GetBuffer ( ) , 32 ) ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : GetDebugString ( char * buffer , size_t len ) {
2017-02-02 17:24:40 +01:00
char endpointsBuf [ 10240 ] ;
memset ( endpointsBuf , 0 , 10240 ) ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
2017-02-02 17:24:40 +01:00
const char * type ;
2017-04-17 20:57:07 +02:00
Endpoint * endpoint = * itrtr ;
switch ( endpoint - > type ) {
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_P2P_INET :
2017-02-02 17:24:40 +01:00
type = " UDP_P2P_INET " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_P2P_LAN :
2017-02-02 17:24:40 +01:00
type = " UDP_P2P_LAN " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_RELAY :
2017-02-02 17:24:40 +01:00
type = " UDP_RELAY " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_TCP_RELAY :
2017-02-02 17:24:40 +01:00
type = " TCP_RELAY " ;
break ;
default :
type = " UNKNOWN " ;
break ;
}
if ( strlen ( endpointsBuf ) > 10240 - 1024 )
break ;
2018-05-15 20:23:46 +02:00
sprintf ( endpointsBuf + strlen ( endpointsBuf ) , " %s:%u %dms %d [%s%s] \n " , endpoint - > address . ToString ( ) . c_str ( ) , endpoint - > port , ( int ) ( endpoint - > averageRTT * 1000 ) , endpoint - > udpPongCount , type , currentEndpoint = = endpoint ? " , IN_USE " : " " ) ;
2017-02-02 17:24:40 +01:00
}
double avgLate [ 3 ] ;
2018-05-15 20:23:46 +02:00
JitterBuffer * jitterBuffer = incomingStreams . size ( ) = = 1 ? incomingStreams [ 0 ] . jitterBuffer : NULL ;
2017-02-02 17:24:40 +01:00
if ( jitterBuffer )
jitterBuffer - > GetAverageLateCount ( avgLate ) ;
else
memset ( avgLate , 0 , 3 * sizeof ( double ) ) ;
snprintf ( buffer , len ,
" Remote endpoints: \n %s "
2017-05-21 16:50:23 +02:00
" Jitter buffer: %d/%.2f | %.1f, %.1f, %.1f \n "
2017-02-02 17:24:40 +01:00
" RTT avg/min: %d/%d \n "
" Congestion window: %d/%d bytes \n "
2018-05-15 20:23:46 +02:00
" Key fingerprint: %02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%s \n "
2017-02-02 17:24:40 +01:00
" Last sent/ack'd seq: %u/%u \n "
" Last recvd seq: %u \n "
2017-03-30 16:06:59 +02:00
" Send/recv losses: %u/%u (%d%%) \n "
2017-02-02 17:24:40 +01:00
" Audio bitrate: %d kbit \n "
// "Packet grouping: %d\n"
" Frame size out/in: %d/%d \n "
" Bytes sent/recvd: %llu/%llu " ,
endpointsBuf ,
2017-05-21 16:50:23 +02:00
jitterBuffer ? jitterBuffer - > GetMinPacketCount ( ) : 0 , jitterBuffer ? jitterBuffer - > GetAverageDelay ( ) : 0 , avgLate [ 0 ] , avgLate [ 1 ] , avgLate [ 2 ] ,
2017-02-02 17:24:40 +01:00
// (int)(GetAverageRTT()*1000), 0,
( int ) ( conctl - > GetAverageRTT ( ) * 1000 ) , ( int ) ( conctl - > GetMinimumRTT ( ) * 1000 ) ,
2017-04-19 15:39:27 +02:00
int ( conctl - > GetInflightDataSize ( ) ) , int ( conctl - > GetCongestionWindow ( ) ) ,
2017-02-02 17:24:40 +01:00
keyFingerprint [ 0 ] , keyFingerprint [ 1 ] , keyFingerprint [ 2 ] , keyFingerprint [ 3 ] , keyFingerprint [ 4 ] , keyFingerprint [ 5 ] , keyFingerprint [ 6 ] , keyFingerprint [ 7 ] ,
2018-05-15 20:23:46 +02:00
useMTProto2 ? " (MTProto2.0) " : " " ,
2017-04-19 15:39:27 +02:00
lastSentSeq , lastRemoteAckSeq , lastRemoteSeq ,
2017-03-30 16:06:59 +02:00
conctl - > GetSendLossCount ( ) , recvLossCount , encoder ? encoder - > GetPacketLoss ( ) : 0 ,
2017-02-02 17:24:40 +01:00
encoder ? ( encoder - > GetBitrate ( ) / 1000 ) : 0 ,
// audioPacketGrouping,
2018-05-15 20:23:46 +02:00
outgoingStreams [ 0 ] . frameDuration , incomingStreams . size ( ) > 0 ? incomingStreams [ 0 ] . frameDuration : 0 ,
2017-04-19 15:39:27 +02:00
( long long unsigned int ) ( stats . bytesSentMobile + stats . bytesSentWifi ) ,
( long long unsigned int ) ( stats . bytesRecvdMobile + stats . bytesRecvdWifi ) ) ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SendPublicEndpointsRequest ( ) {
2017-02-02 17:24:40 +01:00
LOGI ( " Sending public endpoints request " ) ;
2017-04-09 18:14:33 +02:00
if ( preferredRelay ) {
2017-04-17 20:57:07 +02:00
SendPublicEndpointsRequest ( * preferredRelay ) ;
2017-04-09 18:14:33 +02:00
}
if ( peerPreferredRelay & & peerPreferredRelay ! = preferredRelay ) {
2017-04-17 20:57:07 +02:00
SendPublicEndpointsRequest ( * peerPreferredRelay ) ;
2017-04-09 18:14:33 +02:00
}
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SendPublicEndpointsRequest ( Endpoint & relay ) {
2017-07-03 03:42:49 +02:00
if ( ! useUDP )
return ;
2017-04-17 20:57:07 +02:00
LOGD ( " Sending public endpoints request to %s:%d " , relay . address . ToString ( ) . c_str ( ) , relay . port ) ;
2017-02-02 17:24:40 +01:00
publicEndpointsReqTime = GetCurrentTime ( ) ;
waitingForRelayPeerInfo = true ;
2017-04-17 20:57:07 +02:00
unsigned char buf [ 32 ] ;
memcpy ( buf , relay . peerTag , 16 ) ;
2017-02-02 17:24:40 +01:00
memset ( buf + 16 , 0xFF , 16 ) ;
2018-05-15 20:23:46 +02:00
NetworkPacket pkt = { 0 } ;
2017-04-17 20:57:07 +02:00
pkt . data = buf ;
pkt . length = 32 ;
pkt . address = ( NetworkAddress * ) & relay . address ;
pkt . port = relay . port ;
2017-06-07 17:46:59 +02:00
pkt . protocol = PROTO_UDP ;
2017-07-03 03:42:49 +02:00
udpSocket - > Send ( & pkt ) ;
2017-02-02 17:24:40 +01:00
}
2017-04-17 20:57:07 +02:00
Endpoint * VoIPController : : GetEndpointByType ( int type ) {
2018-05-15 20:23:46 +02:00
if ( type = = Endpoint : : TYPE_UDP_RELAY & & preferredRelay )
2017-02-02 17:24:40 +01:00
return preferredRelay ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
if ( ( * itrtr ) - > type = = type )
return * itrtr ;
2017-02-02 17:24:40 +01:00
}
return NULL ;
}
2017-04-17 20:57:07 +02:00
float VoIPController : : GetOutputLevel ( ) {
2017-02-02 17:24:40 +01:00
if ( ! audioOutput | | ! audioOutStarted ) {
return 0.0 ;
}
return audioOutput - > GetLevel ( ) ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SendPacketReliably ( unsigned char type , unsigned char * data , size_t len , double retryInterval , double timeout ) {
2017-04-19 15:39:27 +02:00
LOGD ( " Send reliably, type=%u, len=%u, retry=%.3f, timeout=%.3f " , type , unsigned ( len ) , retryInterval , timeout ) ;
2017-02-02 17:24:40 +01:00
voip_queued_packet_t * pkt = ( voip_queued_packet_t * ) malloc ( sizeof ( voip_queued_packet_t ) ) ;
memset ( pkt , 0 , sizeof ( voip_queued_packet_t ) ) ;
pkt - > type = type ;
if ( data ) {
2017-03-30 16:06:59 +02:00
pkt - > data = ( unsigned char * ) malloc ( len ) ;
2017-02-02 17:24:40 +01:00
memcpy ( pkt - > data , data , len ) ;
pkt - > length = len ;
}
pkt - > retryInterval = retryInterval ;
pkt - > timeout = timeout ;
pkt - > firstSentTime = 0 ;
pkt - > lastSentTime = 0 ;
2018-05-15 20:23:46 +02:00
MutexGuard m ( queuedPacketsMutex ) ;
2017-02-02 17:24:40 +01:00
queuedPackets . push_back ( pkt ) ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : SetConfig ( voip_config_t * cfg ) {
2017-02-02 17:24:40 +01:00
memcpy ( & config , cfg , sizeof ( voip_config_t ) ) ;
2017-03-30 16:06:59 +02:00
if ( tgvoipLogFile ) {
fclose ( tgvoipLogFile ) ;
2018-05-15 20:23:46 +02:00
tgvoipLogFile = NULL ;
2017-03-30 16:06:59 +02:00
}
2017-05-06 01:18:34 +02:00
if ( strlen ( cfg - > logFilePath ) ) {
tgvoipLogFile = fopen ( cfg - > logFilePath , " a " ) ;
2018-05-15 20:23:46 +02:00
tgvoip_log_file_write_header ( tgvoipLogFile ) ;
} else {
tgvoipLogFile = NULL ;
2017-05-06 01:18:34 +02:00
}
2018-05-15 20:23:46 +02:00
if ( statsDump ) {
2017-04-28 13:17:56 +02:00
fclose ( statsDump ) ;
2018-05-15 20:23:46 +02:00
statsDump = NULL ;
}
2017-04-28 13:17:56 +02:00
if ( strlen ( cfg - > statsDumpFilePath ) ) {
statsDump = fopen ( cfg - > statsDumpFilePath , " w " ) ;
2017-07-03 03:42:49 +02:00
if ( statsDump )
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 " , cfg - > statsDumpFilePath ) ;
2018-05-15 20:23:46 +02:00
} else {
statsDump = NULL ;
2017-04-28 13:17:56 +02:00
}
2017-02-02 17:24:40 +01:00
UpdateDataSavingState ( ) ;
UpdateAudioBitrate ( ) ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : UpdateDataSavingState ( ) {
2017-02-02 17:24:40 +01:00
if ( config . data_saving = = DATA_SAVING_ALWAYS ) {
dataSavingMode = true ;
} else if ( config . data_saving = = 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 ;
}
LOGI ( " update data saving mode, config %d, enabled %d, reqd by peer %d " , config . data_saving , dataSavingMode , dataSavingRequestedByPeer ) ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : DebugCtl ( int request , int param ) {
2017-02-02 17:24:40 +01:00
if ( request = = 1 ) { // set bitrate
maxBitrate = param ;
if ( encoder ) {
encoder - > SetBitrate ( maxBitrate ) ;
}
} else if ( request = = 2 ) { // set packet loss
if ( encoder ) {
encoder - > SetPacketLoss ( param ) ;
}
} else if ( request = = 3 ) { // force enable/disable p2p
allowP2p = param = = 1 ;
2018-05-15 20:23:46 +02:00
if ( ! allowP2p & & currentEndpoint & & currentEndpoint - > type ! = Endpoint : : TYPE_UDP_RELAY ) {
2017-02-02 17:24:40 +01:00
currentEndpoint = preferredRelay ;
} else if ( allowP2p ) {
SendPublicEndpointsRequest ( ) ;
}
2017-04-28 13:17:56 +02:00
BufferOutputStream s ( 4 ) ;
2017-02-02 17:24:40 +01:00
s . WriteInt32 ( dataSavingMode ? INIT_FLAG_DATA_SAVING_ENABLED : 0 ) ;
SendPacketReliably ( PKT_NETWORK_CHANGED , s . GetBuffer ( ) , s . GetLength ( ) , 1 , 20 ) ;
} else if ( request = = 4 ) {
if ( echoCanceller )
echoCanceller - > Enable ( param = = 1 ) ;
}
}
2017-04-17 20:57:07 +02:00
const char * VoIPController : : GetVersion ( ) {
2017-02-02 17:24:40 +01:00
return LIBTGVOIP_VERSION ;
}
2017-04-17 20:57:07 +02:00
int64_t VoIPController : : GetPreferredRelayID ( ) {
2017-02-02 17:24:40 +01:00
if ( preferredRelay )
return preferredRelay - > id ;
return 0 ;
}
2017-04-17 20:57:07 +02:00
int VoIPController : : GetLastError ( ) {
2017-02-02 17:24:40 +01:00
return lastError ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : GetStats ( voip_stats_t * stats ) {
2017-02-02 17:24:40 +01:00
memcpy ( stats , & this - > stats , sizeof ( voip_stats_t ) ) ;
}
2017-03-30 16:06:59 +02:00
# ifdef TGVOIP_USE_AUDIO_SESSION
2017-04-17 20:57:07 +02:00
void VoIPController : : SetAcquireAudioSession ( void ( ^ completion ) ( void ( ^ ) ( ) ) ) {
2017-03-30 16:06:59 +02:00
this - > acquireAudioSession = [ completion copy ] ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : ReleaseAudioSession ( void ( ^ completion ) ( ) ) {
2017-03-30 16:06:59 +02:00
completion ( ) ;
}
# endif
2017-04-17 20:57:07 +02:00
void VoIPController : : LogDebugInfo ( ) {
2017-03-30 16:06:59 +02:00
std : : string json = " { \" endpoints \" :[ " ;
2017-04-17 20:57:07 +02:00
for ( std : : vector < Endpoint * > : : iterator itr = endpoints . begin ( ) ; itr ! = endpoints . end ( ) ; + + itr ) {
Endpoint * e = * itr ;
2017-03-30 16:06:59 +02:00
char buffer [ 1024 ] ;
const char * typeStr = " unknown " ;
switch ( e - > type ) {
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_RELAY :
2017-03-30 16:06:59 +02:00
typeStr = " udp_relay " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_P2P_INET :
2017-03-30 16:06:59 +02:00
typeStr = " udp_p2p_inet " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_UDP_P2P_LAN :
2017-03-30 16:06:59 +02:00
typeStr = " udp_p2p_lan " ;
break ;
2018-05-15 20:23:46 +02:00
case Endpoint : : TYPE_TCP_RELAY :
2017-06-06 03:44:16 +02:00
typeStr = " tcp_relay " ;
break ;
2017-03-30 16:06:59 +02:00
}
2017-04-17 20:57:07 +02:00
snprintf ( buffer , 1024 , " { \" address \" : \" %s \" , \" port \" :%u, \" type \" : \" %s \" , \" rtt \" :%u%s%s} " , e - > address . ToString ( ) . c_str ( ) , e - > port , typeStr , ( unsigned int ) round ( e - > averageRTT * 1000 ) , currentEndpoint = = & * e ? " , \" in_use \" :true " : " " , preferredRelay = = & * e ? " , \" preferred \" :true " : " " ) ;
2017-03-30 16:06:59 +02:00
json + = buffer ;
2017-04-17 20:57:07 +02:00
if ( itr ! = endpoints . end ( ) - 1 )
2017-03-30 16:06:59 +02:00
json + = " , " ;
}
json + = " ], " ;
char buffer [ 1024 ] ;
const char * netTypeStr ;
switch ( networkType ) {
case NET_TYPE_WIFI :
netTypeStr = " wifi " ;
break ;
case NET_TYPE_GPRS :
netTypeStr = " gprs " ;
break ;
case NET_TYPE_EDGE :
netTypeStr = " edge " ;
break ;
case NET_TYPE_3G :
netTypeStr = " 3g " ;
break ;
case NET_TYPE_HSPA :
netTypeStr = " hspa " ;
break ;
case NET_TYPE_LTE :
netTypeStr = " lte " ;
break ;
case NET_TYPE_ETHERNET :
netTypeStr = " ethernet " ;
break ;
case NET_TYPE_OTHER_HIGH_SPEED :
netTypeStr = " other_high_speed " ;
break ;
case NET_TYPE_OTHER_LOW_SPEED :
netTypeStr = " other_low_speed " ;
break ;
case NET_TYPE_DIALUP :
netTypeStr = " dialup " ;
break ;
case NET_TYPE_OTHER_MOBILE :
netTypeStr = " other_mobile " ;
break ;
default :
netTypeStr = " unknown " ;
break ;
}
snprintf ( buffer , 1024 , " \" time \" :%u, \" network_type \" : \" %s \" } " , ( unsigned int ) time ( NULL ) , netTypeStr ) ;
json + = buffer ;
debugLogs . push_back ( json ) ;
}
2017-04-17 20:57:07 +02:00
std : : string VoIPController : : GetDebugLog ( ) {
2017-03-30 16:06:59 +02:00
std : : string log = " { \" events \" :[ " ;
for ( std : : vector < std : : string > : : iterator itr = debugLogs . begin ( ) ; itr ! = debugLogs . end ( ) ; + + itr ) {
log + = ( * itr ) ;
2017-04-17 20:57:07 +02:00
if ( ( itr + 1 ) ! = debugLogs . end ( ) )
2017-03-30 16:06:59 +02:00
log + = " , " ;
}
log + = " ], \" libtgvoip_version \" : \" " LIBTGVOIP_VERSION " \" } " ;
return log ;
}
2017-04-17 20:57:07 +02:00
void VoIPController : : GetDebugLog ( char * buffer ) {
2017-03-30 16:06:59 +02:00
strcpy ( buffer , GetDebugLog ( ) . c_str ( ) ) ;
}
2017-04-17 20:57:07 +02:00
size_t VoIPController : : GetDebugLogLength ( ) {
2017-03-30 16:06:59 +02:00
size_t len = 128 ;
for ( std : : vector < std : : string > : : iterator itr = debugLogs . begin ( ) ; itr ! = debugLogs . end ( ) ; + + itr ) {
len + = ( * itr ) . length ( ) + 1 ;
}
return len ;
}
2017-04-28 13:17:56 +02:00
std : : vector < AudioInputDevice > VoIPController : : EnumerateAudioInputs ( ) {
vector < AudioInputDevice > devs ;
audio : : AudioInput : : EnumerateDevices ( devs ) ;
return devs ;
}
std : : vector < AudioOutputDevice > VoIPController : : EnumerateAudioOutputs ( ) {
vector < AudioOutputDevice > devs ;
audio : : AudioOutput : : EnumerateDevices ( devs ) ;
return devs ;
}
void VoIPController : : SetCurrentAudioInput ( std : : string id ) {
currentAudioInput = id ;
if ( audioInput )
audioInput - > SetCurrentDevice ( id ) ;
}
void VoIPController : : SetCurrentAudioOutput ( std : : string id ) {
currentAudioOutput = id ;
if ( audioOutput )
audioOutput - > SetCurrentDevice ( id ) ;
}
std : : string VoIPController : : GetCurrentAudioInputID ( ) {
return currentAudioInput ;
}
std : : string VoIPController : : GetCurrentAudioOutputID ( ) {
return currentAudioOutput ;
}
2017-07-03 03:42:49 +02:00
void VoIPController : : SetProxy ( int protocol , std : : string address , uint16_t port , std : : string username , std : : string password ) {
proxyProtocol = protocol ;
proxyAddress = address ;
proxyPort = port ;
proxyUsername = username ;
proxyPassword = password ;
}
void VoIPController : : SendUdpPing ( Endpoint * endpoint ) {
2018-05-15 20:23:46 +02:00
if ( endpoint - > type ! = Endpoint : : TYPE_UDP_RELAY )
2017-07-03 03:42:49 +02:00
return ;
LOGV ( " Sending UDP ping to %s:%d " , endpoint - > address . ToString ( ) . c_str ( ) , endpoint - > port ) ;
BufferOutputStream p ( 1024 ) ;
p . WriteBytes ( endpoint - > peerTag , 16 ) ;
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 1 ) ;
p . WriteInt32 ( - 2 ) ;
p . WriteInt64 ( 12345 ) ;
2018-05-15 20:23:46 +02:00
NetworkPacket pkt = { 0 } ;
2017-07-03 03:42:49 +02:00
pkt . address = & endpoint - > address ;
pkt . port = endpoint - > port ;
pkt . protocol = PROTO_UDP ;
pkt . data = p . GetBuffer ( ) ;
pkt . length = p . GetLength ( ) ;
udpSocket - > Send ( & pkt ) ;
}
2018-05-15 20:23:46 +02:00
void VoIPGroupController : : SendRecentPacketsRequest ( ) {
BufferOutputStream out ( 1024 ) ;
out . WriteInt32 ( TLID_UDP_REFLECTOR_REQUEST_PACKETS_INFO ) ; // TL function
out . WriteInt32 ( GetCurrentUnixtime ( ) ) ; // date:int
out . WriteInt64 ( 0 ) ; // query_id:long
out . WriteInt32 ( 64 ) ; // recv_num:int
out . WriteInt32 ( 0 ) ; // sent_num:int
SendSpecialReflectorRequest ( out . GetBuffer ( ) , out . GetLength ( ) ) ;
}
void VoIPGroupController : : SendSpecialReflectorRequest ( unsigned char * data , size_t len ) {
BufferOutputStream out ( 1024 ) ;
unsigned char buf [ 1500 ] ;
crypto . rand_bytes ( buf , 8 ) ;
out . WriteBytes ( buf , 8 ) ;
out . WriteInt32 ( ( int32_t ) len ) ;
out . WriteBytes ( data , len ) ;
if ( out . GetLength ( ) % 16 ! = 0 ) {
size_t paddingLen = 16 - ( out . GetLength ( ) % 16 ) ;
crypto . rand_bytes ( buf , paddingLen ) ;
out . WriteBytes ( buf , paddingLen ) ;
}
unsigned char iv [ 16 ] ;
crypto . rand_bytes ( iv , 16 ) ;
unsigned char key [ 32 ] ;
crypto . sha256 ( reflectorSelfSecret , 16 , key ) ;
unsigned char _iv [ 16 ] ;
memcpy ( _iv , iv , 16 ) ;
size_t encryptedLen = out . GetLength ( ) ;
crypto . aes_cbc_encrypt ( out . GetBuffer ( ) , buf , encryptedLen , key , _iv ) ;
out . Reset ( ) ;
out . WriteBytes ( reflectorSelfTag , 16 ) ;
out . WriteBytes ( iv , 16 ) ;
out . WriteBytes ( buf , encryptedLen ) ;
out . WriteBytes ( reflectorSelfSecret , 16 ) ;
crypto . sha256 ( out . GetBuffer ( ) , out . GetLength ( ) , buf ) ;
out . Rewind ( 16 ) ;
out . WriteBytes ( buf , 16 ) ;
NetworkPacket pkt = { 0 } ;
pkt . address = & groupReflector - > address ;
pkt . port = groupReflector - > port ;
pkt . protocol = PROTO_UDP ;
pkt . data = out . GetBuffer ( ) ;
pkt . length = out . GetLength ( ) ;
ActuallySendPacket ( pkt , groupReflector ) ;
}
void VoIPController : : SendRelayPings ( ) {
//LOGV("Send relay pings 1");
if ( ( state = = STATE_ESTABLISHED | | state = = STATE_RECONNECTING ) & & endpoints . size ( ) > 1 ) {
Endpoint * minPingRelay = preferredRelay ;
double minPing = preferredRelay - > averageRTT * ( preferredRelay - > type = = Endpoint : : TYPE_TCP_RELAY ? 2 : 1 ) ;
for ( std : : vector < Endpoint * > : : iterator e = endpoints . begin ( ) ; e ! = endpoints . end ( ) ; + + e ) {
Endpoint * endpoint = * e ;
if ( endpoint - > type = = Endpoint : : TYPE_TCP_RELAY & & ! useTCP )
continue ;
if ( GetCurrentTime ( ) - endpoint - > lastPingTime > = 10 ) {
LOGV ( " Sending ping to %s " , endpoint - > address . ToString ( ) . c_str ( ) ) ;
unsigned char * buf = outgoingPacketsBufferPool . Get ( ) ;
if ( buf ) {
sendQueue - > Put ( PendingOutgoingPacket {
/*.seq=*/ ( endpoint - > lastPingSeq = GenerateOutSeq ( ) ) ,
/*.type=*/ PKT_PING ,
/*.len=*/ 0 ,
/*.data=*/ buf ,
/*.endpoint=*/ endpoint
} ) ;
}
endpoint - > lastPingTime = GetCurrentTime ( ) ;
}
if ( 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 ;
}
}
}
if ( minPingRelay ! = preferredRelay ) {
preferredRelay = minPingRelay ;
LOGV ( " set preferred relay to %s " , preferredRelay - > address . ToString ( ) . c_str ( ) ) ;
if ( currentEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY | | currentEndpoint - > type = = Endpoint : : TYPE_TCP_RELAY )
currentEndpoint = preferredRelay ;
LogDebugInfo ( ) ;
/*BufferOutputStream pkt(32);
pkt . WriteInt64 ( preferredRelay - > id ) ;
SendPacketReliably ( PKT_SWITCH_PREF_RELAY , pkt . GetBuffer ( ) , pkt . GetLength ( ) , 1 , 9 ) ; */
}
if ( currentEndpoint - > type = = Endpoint : : TYPE_UDP_RELAY ) {
Endpoint * p2p = GetEndpointByType ( Endpoint : : TYPE_UDP_P2P_INET ) ;
if ( p2p ) {
Endpoint * lan = GetEndpointByType ( Endpoint : : TYPE_UDP_P2P_LAN ) ;
if ( lan & & lan - > averageRTT > 0 & & lan - > averageRTT < minPing * relayToP2pSwitchThreshold ) {
//SendPacketReliably(PKT_SWITCH_TO_P2P, NULL, 0, 1, 5);
currentEndpoint = lan ;
LOGI ( " Switching to p2p (LAN) " ) ;
LogDebugInfo ( ) ;
} else {
if ( p2p - > averageRTT > 0 & & p2p - > averageRTT < minPing * relayToP2pSwitchThreshold ) {
//SendPacketReliably(PKT_SWITCH_TO_P2P, NULL, 0, 1, 5);
currentEndpoint = p2p ;
LOGI ( " Switching to p2p (Inet) " ) ;
LogDebugInfo ( ) ;
}
}
}
} else {
if ( minPing > 0 & & minPing < currentEndpoint - > averageRTT * p2pToRelaySwitchThreshold ) {
LOGI ( " Switching to relay " ) ;
currentEndpoint = preferredRelay ;
LogDebugInfo ( ) ;
}
}
}
}
void VoIPGroupController : : SendRelayPings ( ) {
//LOGV("Send relay pings 2");
double currentTime = GetCurrentTime ( ) ;
if ( currentTime - groupReflector - > lastPingTime > = 0.25 ) {
SendRecentPacketsRequest ( ) ;
groupReflector - > lastPingTime = currentTime ;
}
}
void VoIPController : : StartAudio ( ) {
Stream & outgoingAudioStream = outgoingStreams [ 0 ] ;
LOGI ( " before create audio io " ) ;
void * platformSpecific = NULL ;
# ifdef __APPLE__
platformSpecific = appleAudioIO ;
# endif
audioInput = tgvoip : : audio : : AudioInput : : Create ( currentAudioInput , platformSpecific ) ;
audioInput - > Configure ( 48000 , 16 , 1 ) ;
audioOutput = tgvoip : : audio : : AudioOutput : : Create ( currentAudioOutput , platformSpecific ) ;
audioOutput - > Configure ( 48000 , 16 , 1 ) ;
echoCanceller = new EchoCanceller ( config . enableAEC , config . enableNS , config . enableAGC ) ;
encoder = new OpusEncoder ( audioInput ) ;
encoder - > SetCallback ( AudioInputCallback , this ) ;
encoder - > SetOutputFrameDuration ( outgoingAudioStream . frameDuration ) ;
encoder - > SetEchoCanceller ( echoCanceller ) ;
encoder - > Start ( ) ;
if ( ! micMuted ) {
audioInput - > Start ( ) ;
if ( ! audioInput - > IsInitialized ( ) ) {
LOGE ( " Erorr initializing audio capture " ) ;
lastError = ERROR_AUDIO_IO ;
SetState ( STATE_FAILED ) ;
return ;
}
}
if ( ! audioOutput - > IsInitialized ( ) ) {
LOGE ( " Erorr initializing audio playback " ) ;
lastError = ERROR_AUDIO_IO ;
SetState ( STATE_FAILED ) ;
return ;
}
UpdateAudioBitrate ( ) ;
/*voip_stream_t* incomingAudioStream=incomingStreams[0];
jitterBuffer = new JitterBuffer ( NULL , incomingAudioStream - > frameDuration ) ;
decoder = new OpusDecoder ( audioOutput ) ;
decoder - > SetEchoCanceller ( echoCanceller ) ;
decoder - > SetJitterBuffer ( jitterBuffer ) ;
decoder - > SetFrameDuration ( incomingAudioStream - > frameDuration ) ;
decoder - > Start ( ) ;
if ( incomingAudioStream - > frameDuration > 50 )
jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_60 " , 3 ) ) ;
else if ( incomingAudioStream - > frameDuration > 30 )
jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_40 " , 4 ) ) ;
else
jitterBuffer - > SetMinPacketCount ( ( uint32_t ) ServerConfig : : GetSharedInstance ( ) - > GetInt ( " jitter_initial_delay_20 " , 6 ) ) ; */
//audioOutput->Start();
OnAudioOutputReady ( ) ;
}
void VoIPController : : OnAudioOutputReady ( ) {
Stream & stm = incomingStreams [ 0 ] ;
outputAGC = new AutomaticGainControl ( ) ;
outputAGC - > SetPassThrough ( ! outputAGCEnabled ) ;
stm . decoder = new OpusDecoder ( audioOutput , true ) ;
stm . decoder - > AddAudioEffect ( outputAGC ) ;
stm . decoder - > SetEchoCanceller ( echoCanceller ) ;
stm . decoder - > SetJitterBuffer ( stm . jitterBuffer ) ;
stm . decoder - > SetFrameDuration ( stm . frameDuration ) ;
stm . decoder - > Start ( ) ;
}
void VoIPGroupController : : OnAudioOutputReady ( ) {
encoder - > SetDTX ( true ) ;
audioMixer - > SetOutput ( audioOutput ) ;
audioMixer - > SetEchoCanceller ( echoCanceller ) ;
audioMixer - > Start ( ) ;
audioOutput - > Start ( ) ;
audioOutStarted = true ;
encoder - > SetLevelMeter ( & selfLevelMeter ) ;
}
void VoIPGroupController : : WritePacketHeader ( uint32_t seq , BufferOutputStream * s , unsigned char type , uint32_t length ) {
s - > WriteInt32 ( TLID_DECRYPTED_AUDIO_BLOCK ) ;
int64_t randomID ;
crypto . rand_bytes ( ( uint8_t * ) & randomID , 8 ) ;
s - > WriteInt64 ( randomID ) ;
unsigned char randBytes [ 7 ] ;
crypto . rand_bytes ( randBytes , 7 ) ;
s - > WriteByte ( 7 ) ;
s - > WriteBytes ( randBytes , 7 ) ;
uint32_t pflags = PFLAG_HAS_SEQ | PFLAG_HAS_SENDER_TAG_HASH ;
if ( length > 0 )
pflags | = PFLAG_HAS_DATA ;
pflags | = ( ( uint32_t ) type ) < < 24 ;
s - > WriteInt32 ( pflags ) ;
if ( type = = PKT_STREAM_DATA | | type = = PKT_STREAM_DATA_X2 | | type = = PKT_STREAM_DATA_X3 ) {
conctl - > PacketSent ( seq , length ) ;
}
/*if(pflags & PFLAG_HAS_CALL_ID){
s - > WriteBytes ( callID , 16 ) ;
} */
//s->WriteInt32(lastRemoteSeq);
s - > WriteInt32 ( seq ) ;
s - > WriteBytes ( reflectorSelfTagHash , 16 ) ;
if ( length > 0 ) {
if ( length < = 253 ) {
s - > WriteByte ( ( unsigned char ) length ) ;
} else {
s - > WriteByte ( 254 ) ;
s - > WriteByte ( ( unsigned char ) ( length & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 8 ) & 0xFF ) ) ;
s - > WriteByte ( ( unsigned char ) ( ( length > > 16 ) & 0xFF ) ) ;
}
}
}
void VoIPGroupController : : SendPacket ( unsigned char * data , size_t len , Endpoint * ep , PendingOutgoingPacket & srcPacket ) {
if ( stopping )
return ;
if ( ep - > type = = Endpoint : : TYPE_TCP_RELAY & & ! useTCP )
return ;
BufferOutputStream out ( len + 128 ) ;
//LOGV("send group packet %u", len);
out . WriteBytes ( reflectorSelfTag , 16 ) ;
if ( len > 0 ) {
BufferOutputStream inner ( len + 128 ) ;
inner . WriteInt32 ( ( uint32_t ) len ) ;
inner . WriteBytes ( data , len ) ;
size_t padLen = 16 - inner . GetLength ( ) % 16 ;
if ( padLen < 12 )
padLen + = 16 ;
unsigned char padding [ 28 ] ;
crypto . rand_bytes ( ( uint8_t * ) padding , padLen ) ;
inner . WriteBytes ( padding , padLen ) ;
assert ( inner . GetLength ( ) % 16 = = 0 ) ;
unsigned char key [ 32 ] , iv [ 32 ] , msgKey [ 16 ] ;
out . WriteBytes ( keyFingerprint , 8 ) ;
BufferOutputStream buf ( len + 32 ) ;
size_t x = 0 ;
buf . WriteBytes ( encryptionKey + 88 + x , 32 ) ;
buf . WriteBytes ( inner . GetBuffer ( ) + 4 , inner . GetLength ( ) - 4 ) ;
unsigned char msgKeyLarge [ 32 ] ;
crypto . sha256 ( buf . GetBuffer ( ) , buf . GetLength ( ) , msgKeyLarge ) ;
memcpy ( msgKey , msgKeyLarge + 8 , 16 ) ;
KDF2 ( msgKey , 0 , 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 ( ) ) ;
}
// relay signature
out . WriteBytes ( reflectorSelfSecret , 16 ) ;
unsigned char sig [ 32 ] ;
crypto . sha256 ( out . GetBuffer ( ) , out . GetLength ( ) , sig ) ;
out . Rewind ( 16 ) ;
out . WriteBytes ( sig , 16 ) ;
if ( srcPacket . type = = PKT_STREAM_DATA | | srcPacket . type = = PKT_STREAM_DATA_X2 | | srcPacket . type = = PKT_STREAM_DATA_X3 ) {
PacketIdMapping mapping = { srcPacket . seq , * reinterpret_cast < uint16_t * > ( sig + 14 ) , 0 } ;
MutexGuard m ( sentPacketsMutex ) ;
recentSentPackets . push_back ( mapping ) ;
//LOGD("sent packet with id: %04X", mapping.id);
while ( recentSentPackets . size ( ) > 64 )
recentSentPackets . erase ( recentSentPackets . begin ( ) ) ;
}
lastSentSeq = srcPacket . seq ;
if ( IS_MOBILE_NETWORK ( networkType ) )
stats . bytesSentMobile + = ( uint64_t ) out . GetLength ( ) ;
else
stats . bytesSentWifi + = ( uint64_t ) out . GetLength ( ) ;
NetworkPacket pkt = { 0 } ;
pkt . address = ( NetworkAddress * ) & ep - > address ;
pkt . port = ep - > port ;
pkt . length = out . GetLength ( ) ;
pkt . data = out . GetBuffer ( ) ;
pkt . protocol = ep - > type = = Endpoint : : TYPE_TCP_RELAY ? PROTO_TCP : PROTO_UDP ;
ActuallySendPacket ( pkt , ep ) ;
}
2017-08-21 18:02:37 +02:00
int VoIPController : : GetSignalBarsCount ( ) {
2017-09-07 07:39:33 +02:00
unsigned char avg = 0 ;
2018-05-15 20:23:46 +02:00
for ( unsigned int i = 0 ; i < sizeof ( signalBarsHistory ) ; i + + )
2017-09-07 07:39:33 +02:00
avg + = signalBarsHistory [ i ] ;
return avg > > 2 ;
2017-08-21 18:02:37 +02:00
}
2018-05-15 20:23:46 +02:00
float VoIPGroupController : : GetParticipantAudioLevel ( int32_t userID ) {
if ( userID = = userSelfID )
return selfLevelMeter . GetLevel ( ) ;
MutexGuard m ( participantsMutex ) ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( p - > userID = = userID ) {
return p - > levelMeter - > GetLevel ( ) ;
}
}
return 0 ;
}
void VoIPGroupController : : SetMicMute ( bool mute ) {
micMuted = mute ;
if ( audioInput ) {
if ( mute )
audioInput - > Stop ( ) ;
else
audioInput - > Start ( ) ;
if ( ! audioInput - > IsInitialized ( ) ) {
lastError = ERROR_AUDIO_IO ;
SetState ( STATE_FAILED ) ;
return ;
}
}
outgoingStreams [ 0 ] . enabled = ! mute ;
SerializeAndUpdateOutgoingStreams ( ) ;
}
void VoIPGroupController : : SetParticipantVolume ( int32_t userID , float volume ) {
MutexGuard m ( participantsMutex ) ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
if ( p - > userID = = userID ) {
for ( std : : vector < Stream > : : iterator s = p - > streams . begin ( ) ; s ! = p - > streams . end ( ) ; + + s ) {
if ( s - > type = = STREAM_TYPE_AUDIO ) {
if ( s - > decoder ) {
float db ;
if ( volume = = 0.0f )
db = - INFINITY ;
else if ( volume < 1.0f )
db = - 50.0f * ( 1.0f - volume ) ;
else if ( volume > 1.0f & & volume < = 2.0f )
db = 10.0f * ( volume - 1.0f ) ;
else
db = 0.0f ;
//LOGV("Setting user %u audio volume to %.2f dB", userID, db);
audioMixer - > SetInputVolume ( s - > callbackWrapper , db ) ;
}
break ;
}
}
break ;
}
}
}
void VoIPGroupController : : SerializeAndUpdateOutgoingStreams ( ) {
BufferOutputStream out ( 1024 ) ;
out . WriteByte ( ( unsigned char ) outgoingStreams . size ( ) ) ;
for ( std : : vector < Stream > : : iterator s = outgoingStreams . begin ( ) ; s ! = outgoingStreams . end ( ) ; + + s ) {
BufferOutputStream o ( 128 ) ;
o . WriteByte ( s - > id ) ;
o . WriteByte ( s - > type ) ;
o . WriteInt32 ( s - > codec ) ;
o . WriteInt32 ( ( unsigned char ) ( ( s - > enabled ? STREAM_FLAG_ENABLED : 0 ) | STREAM_FLAG_DTX ) ) ;
o . WriteInt16 ( s - > frameDuration ) ;
out . WriteInt16 ( ( int16_t ) o . GetLength ( ) ) ;
out . WriteBytes ( o . GetBuffer ( ) , o . GetLength ( ) ) ;
}
if ( groupCallbacks . updateStreams )
groupCallbacks . updateStreams ( this , out . GetBuffer ( ) , out . GetLength ( ) ) ;
}
void VoIPGroupController : : SetCallbacks ( VoIPGroupController : : Callbacks callbacks ) {
VoIPController : : SetCallbacks ( callbacks ) ;
this - > groupCallbacks = callbacks ;
}
void VoIPController : : SetCallbacks ( VoIPController : : Callbacks callbacks ) {
this - > callbacks = callbacks ;
if ( callbacks . connectionStateChanged )
callbacks . connectionStateChanged ( this , state ) ;
2017-08-21 18:02:37 +02:00
}
2017-09-07 07:39:33 +02:00
void VoIPController : : SetAudioOutputGainControlEnabled ( bool enabled ) {
LOGD ( " New output AGC state: %d " , enabled ) ;
outputAGCEnabled = enabled ;
if ( outputAGC )
outputAGC - > SetPassThrough ( ! enabled ) ;
}
2018-05-15 20:23:46 +02:00
uint32_t VoIPController : : GetPeerCapabilities ( ) {
return peerCapabilities ;
}
void VoIPController : : SendGroupCallKey ( unsigned char * key ) {
if ( ! ( peerCapabilities & TGVOIP_PEER_CAP_GROUP_CALLS ) ) {
LOGE ( " Tried to send group call key but peer isn't capable of them " ) ;
return ;
}
if ( didSendGroupCallKey ) {
LOGE ( " Tried to send a group call key repeatedly " ) ;
return ;
}
if ( ! isOutgoing ) {
LOGE ( " You aren't supposed to send group call key in an incoming call, use VoIPController::RequestCallUpgrade() instead " ) ;
return ;
}
didSendGroupCallKey = true ;
SendPacketReliably ( PKT_GROUP_CALL_KEY , key , 256 , 0.5 , 20 ) ;
}
void VoIPController : : RequestCallUpgrade ( ) {
if ( ! ( peerCapabilities & TGVOIP_PEER_CAP_GROUP_CALLS ) ) {
LOGE ( " Tried to send group call key but peer isn't capable of them " ) ;
return ;
}
if ( didSendUpgradeRequest ) {
LOGE ( " Tried to send upgrade request repeatedly " ) ;
return ;
}
if ( isOutgoing ) {
LOGE ( " You aren't supposed to send an upgrade request in an outgoing call, generate an encryption key and use VoIPController::SendGroupCallKey instead " ) ;
return ;
}
didSendUpgradeRequest = true ;
SendPacketReliably ( PKT_REQUEST_GROUP , NULL , 0 , 0.5 , 20 ) ;
}
void VoIPGroupController : : GetDebugString ( char * buffer , size_t len ) {
char endpointsBuf [ 10240 ] ;
memset ( endpointsBuf , 0 , 10240 ) ;
for ( std : : vector < Endpoint * > : : iterator itrtr = endpoints . begin ( ) ; itrtr ! = endpoints . end ( ) ; + + itrtr ) {
const char * type ;
Endpoint * endpoint = * itrtr ;
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 ;
}
if ( strlen ( endpointsBuf ) > 10240 - 1024 )
break ;
sprintf ( endpointsBuf + strlen ( endpointsBuf ) , " %s:%u %dms [%s%s] \n " , endpoint - > address . ToString ( ) . c_str ( ) , endpoint - > port , ( int ) ( endpoint - > averageRTT * 1000 ) , type , currentEndpoint = = endpoint ? " , IN_USE " : " " ) ;
}
double avgLate [ 3 ] ;
JitterBuffer * jitterBuffer = incomingStreams . size ( ) = = 1 ? incomingStreams [ 0 ] . jitterBuffer : NULL ;
if ( jitterBuffer )
jitterBuffer - > GetAverageLateCount ( avgLate ) ;
else
memset ( avgLate , 0 , 3 * sizeof ( double ) ) ;
snprintf ( buffer , len ,
" Remote endpoints: \n %s "
" RTT avg/min: %d/%d \n "
" Congestion window: %d/%d bytes \n "
" Key fingerprint: %02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX \n "
" Last sent/ack'd seq: %u/%u \n "
" Send/recv losses: %u/%u (%d%%) \n "
" Audio bitrate: %d kbit \n "
" Bytes sent/recvd: %llu/%llu \n \n " ,
endpointsBuf ,
( int ) ( conctl - > GetAverageRTT ( ) * 1000 ) , ( int ) ( conctl - > GetMinimumRTT ( ) * 1000 ) ,
int ( conctl - > GetInflightDataSize ( ) ) , int ( conctl - > GetCongestionWindow ( ) ) ,
keyFingerprint [ 0 ] , keyFingerprint [ 1 ] , keyFingerprint [ 2 ] , keyFingerprint [ 3 ] , keyFingerprint [ 4 ] , keyFingerprint [ 5 ] , keyFingerprint [ 6 ] , keyFingerprint [ 7 ] ,
lastSentSeq , lastRemoteAckSeq ,
conctl - > GetSendLossCount ( ) , recvLossCount , encoder ? encoder - > GetPacketLoss ( ) : 0 ,
encoder ? ( encoder - > GetBitrate ( ) / 1000 ) : 0 ,
( long long unsigned int ) ( stats . bytesSentMobile + stats . bytesSentWifi ) ,
( long long unsigned int ) ( stats . bytesRecvdMobile + stats . bytesRecvdWifi ) ) ;
MutexGuard m ( participantsMutex ) ;
for ( std : : vector < GroupCallParticipant > : : iterator p = participants . begin ( ) ; p ! = participants . end ( ) ; + + p ) {
snprintf ( endpointsBuf , sizeof ( endpointsBuf ) , " Participant id: %d \n " , p - > userID ) ;
if ( strlen ( buffer ) + strlen ( endpointsBuf ) > len )
return ;
strcat ( buffer , endpointsBuf ) ;
for ( std : : vector < Stream > : : iterator stm = p - > streams . begin ( ) ; stm ! = p - > streams . end ( ) ; + + stm ) {
char * codec = reinterpret_cast < char * > ( & stm - > codec ) ;
snprintf ( endpointsBuf , sizeof ( endpointsBuf ) , " Stream %d (type %d, codec '%c%c%c%c', %sabled) \n " ,
stm - > id , stm - > type , codec [ 3 ] , codec [ 2 ] , codec [ 1 ] , codec [ 0 ] , stm - > enabled ? " en " : " dis " ) ;
if ( strlen ( buffer ) + strlen ( endpointsBuf ) > len )
return ;
strcat ( buffer , endpointsBuf ) ;
if ( stm - > enabled ) {
if ( stm - > jitterBuffer ) {
snprintf ( endpointsBuf , sizeof ( endpointsBuf ) , " Jitter buffer: %d/%.2f \n " ,
stm - > jitterBuffer - > GetMinPacketCount ( ) , stm - > jitterBuffer - > GetAverageDelay ( ) ) ;
if ( strlen ( buffer ) + strlen ( endpointsBuf ) > len )
return ;
strcat ( buffer , endpointsBuf ) ;
}
}
}
strcat ( buffer , " \n " ) ;
}
}
int32_t VoIPGroupController : : GetCurrentUnixtime ( ) {
return time ( NULL ) + timeDifference ;
}
2017-12-27 18:25:47 +01:00
void VoIPController : : SetEchoCancellationStrength ( int strength ) {
echoCancellationStrength = strength ;
if ( echoCanceller )
echoCanceller - > SetAECStrength ( strength ) ;
}
2017-04-17 20:57:07 +02:00
Endpoint : : Endpoint ( int64_t id , uint16_t port , IPv4Address & _address , IPv6Address & _v6address , char type , unsigned char peerTag [ 16 ] ) : address ( _address ) , v6address ( _v6address ) {
this - > id = id ;
this - > port = port ;
this - > type = type ;
memcpy ( this - > peerTag , peerTag , 16 ) ;
2018-05-15 20:23:46 +02:00
if ( type = = TYPE_UDP_RELAY & & ServerConfig : : GetSharedInstance ( ) - > GetBoolean ( " force_tcp " , false ) )
this - > type = TYPE_TCP_RELAY ;
2017-04-17 20:57:07 +02:00
lastPingSeq = 0 ;
lastPingTime = 0 ;
averageRTT = 0 ;
memset ( rtts , 0 , sizeof ( rtts ) ) ;
2017-07-03 03:42:49 +02:00
socket = NULL ;
2018-05-15 20:23:46 +02:00
udpPongCount = 0 ;
2017-04-17 20:57:07 +02:00
}
2017-03-30 16:06:59 +02:00
2017-04-17 20:57:07 +02:00
Endpoint : : Endpoint ( ) : address ( 0 ) , v6address ( " ::0 " ) {
2017-05-14 15:28:17 +02:00
lastPingSeq = 0 ;
lastPingTime = 0 ;
averageRTT = 0 ;
memset ( rtts , 0 , sizeof ( rtts ) ) ;
2017-07-03 03:42:49 +02:00
socket = NULL ;
2018-05-15 20:23:46 +02:00
udpPongCount = 0 ;
2017-04-17 20:57:07 +02:00
}