2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <memory> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <misc/endianness.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <log/LogUtils.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <ThreadPool/Timer.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <regex> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <src/build.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <Properties.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "src/channel/ClientChannelView.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "SpeakingClient.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "src/InstanceHandler.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "StringVariable.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "src/music/MusicBotManager.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  "misc/timer.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  namespace  std : : chrono ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  namespace  ts ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  namespace  ts : : server ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								using  namespace  ts : : protocol ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//#define PKT_LOG_VOICE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//#define PKT_LOG_WHISPER
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  SpeakingClient : : shouldReceiveVoice ( const  std : : shared_ptr < ConnectedClient >  & sender )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    //if(this->properties()[property::CLIENT_AWAY].as<bool>()) return false;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! this - > properties ( ) [ property : : CLIENT_OUTPUT_HARDWARE ] . as < bool > ( ) )  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( this - > properties ( ) [ property : : CLIENT_OUTPUT_MUTED ] . as < bool > ( ) )  return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        shared_lock  client_lock ( this - > channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto &  entry  :  this - > mutedClients ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( entry . lock ( )  = =  sender ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  SpeakingClient : : shouldReceiveVoiceWhisper ( const  std : : shared_ptr < ConnectedClient >  & sender )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if ( ! this - > shouldReceiveVoice ( sender ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  required_permission  =  this - > cached_permission_value ( permission : : i_client_needed_whisper_power ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( required_permission  = =  permNotGranted ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  granted_permission  =  sender - > cached_permission_value ( permission : : i_client_whisper_power ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  granted_permission  > =  required_permission ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : handlePacketVoice ( const  pipes : : buffer_view &  data ,  bool  head ,  bool  fragmented )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  server  =  this - > getServer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  self  =  _this . lock ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! self  | |  ! server )  return ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( data . length ( )  <  3 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        this - > disconnect ( " invalid packet (Voice; Length:  "  +  to_string ( data . length ( ) )  +  " ) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  current_channel  =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! current_channel )  {  return ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! this - > allowedToTalk )  {  return ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    this - > updateSpeak ( false ,  system_clock : : now ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > resetIdleTime ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  target_clients  =  this - > server - > getClientsByChannel ( current_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    target_clients . erase ( std : : remove_if ( target_clients . begin ( ) ,  target_clients . end ( ) ,  [ & ] ( const  shared_ptr < ConnectedClient > &  client )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if ( client  = =  this )  return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  speaking_client  =  dynamic_pointer_cast < SpeakingClient > ( client ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( ! speaking_client )  return  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  ! speaking_client - > shouldReceiveVoice ( self ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ) ,  target_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( target_clients . empty ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    VoicePacketFlags  flags { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . head  =  head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . fragmented  =  fragmented ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . new_protocol  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //crypt_mode = 1 | disabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //crypt_mode = 2 | enabled
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  crypt_mode  =  this - > server - > voice_encryption_mode ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( crypt_mode  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            flags . encrypted  =  ! current_channel - > properties ( ) [ property : : CHANNEL_CODEC_IS_UNENCRYPTED ] . as < bool > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            flags . encrypted  =  crypt_mode  = =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    uint16_t  vpacketId  =  be2le16 ( ( char * )  data . data_ptr ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  codec  =  ( uint8_t )  data [ 2 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PKT_LOG_VOICE 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logTrace ( lstream  < <  CLIENT_LOG_PREFIX  < <  " Voice length:  "  < <  data . length ( )  < <  "  -> id:  "  < <  vpacketId  < <  "  codec:  "  < <  ( int )  codec  < <  "  head:  "  < <  head  < <  "  fragmented:  "  < <  fragmented ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    char  buffer [ data . length ( )  +  2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    le2be16 ( vpacketId ,  & buffer [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    le2be16 ( getClientId ( ) ,  & buffer [ 2 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    buffer [ 4 ]  =  codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( data . length ( )  -  3  >  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        memcpy ( & buffer [ 5 ] ,  & data [ 3 ] ,  data . length ( )  -  3 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( const  auto &  client  :  target_clients )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  speaking_client  =  static_pointer_cast < SpeakingClient > ( client ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        speaking_client - > send_voice_packet ( pipes : : buffer_view { buffer ,  data . length ( )  +  2 } ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//2 + 2 + 8
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define OUT_WHISPER_PKT_OFFSET 5 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//#define PKT_LOG_WHISPER
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								enum  WhisperType  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    SERVER_GROUP  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_GROUP  =  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_COMMANDER  =  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ALL  =  3 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								enum  WhisperTarget  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    CHANNEL_ALL  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_CURRENT  =  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_PARENT  =  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_ALL_PARENT  =  3 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_FAMILY  =  4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_COMPLETE_FAMILY  =  5 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    CHANNEL_SUBCHANNELS  =  6 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//All clients => type := SERVER_GROUP and target_id := 0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Server group => type := SERVER_GROUP and target_id := <server group id>
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Channel group => type := CHANNEL_GROUP and target_id := <channel group id>
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Channel commander => type := CHANNEL_COMMANDER and target_id := 0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : handlePacketVoiceWhisper ( const  pipes : : buffer_view &  data ,  bool  new_packet )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if ( data . length ( )  <  5 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > disconnect ( " Invalid packet (Voice whisper) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " {} Tried to send a too short whisper packet. Length: {} " ,  CLIENT_STR_LOG_PREFIX ,  data . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint16_t  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  vpacketId  =  be2le16 ( ( char * )  data . data_ptr ( ) ,  offset ,  & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  codec  =  ( uint8_t )  data [ offset + + ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    VoicePacketFlags  flags { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . head  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . fragmented  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    flags . new_protocol  =  new_packet ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( new_packet )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( data . length ( )  <  7 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > disconnect ( " Invalid packet (Voice whisper | New) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            logMessage ( this - > getServerId ( ) ,  " {} Tried to send a too short whisper packet. Length: {} " ,  CLIENT_STR_LOG_PREFIX ,  data . length ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  type  =  ( WhisperType )  data [ offset + + ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  target  =  ( WhisperTarget )  data [ offset + + ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  type_id  =  be2le64 ( ( char * )  data . data_ptr ( ) ,  offset ,  & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > resetIdleTime ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        size_t  data_length  =  data . length ( )  -  offset ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PKT_LOG_WHISPER 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        logTrace ( this - > getServerId ( ) ,  " {} Whisper data length: {}. Type: {}. Target: {}. Target ID: {}. " ,  CLIENT_STR_LOG_PREFIX ,  data_length ,  type ,  target ,  type_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        deque < shared_ptr < SpeakingClient > >  available_clients ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto &  client  :  this - > server - > getClients ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  speakingClient  =  dynamic_pointer_cast < SpeakingClient > ( client ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! speakingClient  | |  client  = =  this )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! speakingClient - > currentChannel )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( type  = =  WhisperType : : ALL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                available_clients . push_back ( speakingClient ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  if ( type  = =  WhisperType : : SERVER_GROUP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( type_id  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    available_clients . push_back ( speakingClient ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    shared_lock  client_lock ( this - > channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    for ( const  auto &  id  :  client - > cached_server_groups )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if ( id  = =  type_id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            available_clients . push_back ( speakingClient ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  if ( type  = =  WhisperType : : CHANNEL_GROUP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( client - > cached_channel_group  = =  type_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    available_clients . push_back ( speakingClient ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  if ( type  = =  WhisperType : : CHANNEL_COMMANDER )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( client - > properties ( ) [ property : : CLIENT_IS_CHANNEL_COMMANDER ] . as < bool > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    available_clients . push_back ( speakingClient ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( target  = =  WhisperTarget : : CHANNEL_CURRENT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  target - > currentChannel  ! =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( target  = =  WhisperTarget : : CHANNEL_PARENT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  current_parent  =  this - > currentChannel - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! current_parent )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  target - > currentChannel  ! =  current_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( target  = =  WhisperTarget : : CHANNEL_ALL_PARENT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shared_ptr < BasicChannel >  current_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                current_parent  =  this - > currentChannel - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( ! current_parent )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                auto  tmp_parent  =  current_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                while ( tmp_parent  & &  tmp_parent  ! =  target - > currentChannel ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    tmp_parent  =  tmp_parent - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  target - > currentChannel  ! =  tmp_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( target  = =  WhisperTarget : : CHANNEL_FAMILY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shared_ptr < BasicChannel >  current  =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                auto  tmp_current  =  target - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                while ( tmp_current  & &  tmp_current  ! =  current ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    tmp_current  =  tmp_current - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  current  ! =  tmp_current ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( target  = =  WhisperTarget : : CHANNEL_COMPLETE_FAMILY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shared_ptr < BasicChannel >  current  =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            while ( current  & &  current - > parent ( ) )  current  =  current - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                auto  tmp_current  =  target - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                while ( tmp_current  & &  tmp_current  ! =  current ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    tmp_current  =  tmp_current - > parent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  current  ! =  tmp_current ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( target  = =  WhisperTarget : : CHANNEL_SUBCHANNELS )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shared_ptr < BasicChannel >  current  =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            available_clients . erase ( std : : remove_if ( available_clients . begin ( ) ,  available_clients . end ( ) ,  [ & ] ( const  shared_ptr < SpeakingClient > &  target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  target - > currentChannel - > parent ( )  ! =  current ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ) ,  available_clients . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( available_clients . empty ( ) )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //Create the packet data
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        char  packet_buffer [ OUT_WHISPER_PKT_OFFSET  +  data_length ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( offset  <  data . length ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            memcpy ( & packet_buffer [ OUT_WHISPER_PKT_OFFSET ] ,  & data [ offset ] ,  data_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        le2be16 ( vpacketId ,  packet_buffer ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        le2be16 ( this - > getClientId ( ) ,  packet_buffer ,  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        packet_buffer [ 4 ]  =  codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        VoicePacketFlags  flags { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  data  =  pipes : : buffer_view ( packet_buffer ,  OUT_WHISPER_PKT_OFFSET  +  data_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto &  cl  :  available_clients ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( cl - > shouldReceiveVoiceWhisper ( _this . lock ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                cl - > send_voice_whisper_packet ( data ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > updateSpeak ( false ,  system_clock : : now ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  clientCount  =  ( uint8_t )  data [ offset + + ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  channelCount  =  ( uint8_t )  data [ offset + + ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( data . length ( )  <  5  +  channelCount  *  2  +  clientCount  *  8 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            logMessage ( this - > getServerId ( ) ,  " {} Tried to send a too short whisper packet. Length: {} Required: {} " ,  CLIENT_STR_LOG_PREFIX ,  data . length ( ) ,  to_string ( 5  +  channelCount  *  2  +  clientCount  *  8 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > resetIdleTime ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ChannelId  channelIds [ clientCount ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ClientId  clientIds [ channelCount ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( uint8_t  index  =  0 ;  index  <  clientCount ;  index + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            channelIds [ index ]  =  be2le64 ( ( char * )  data . data_ptr ( ) ,  offset ,  & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( uint8_t  index  =  0 ;  index  <  channelCount ;  index + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            clientIds [ index ]  =  be2le16 ( ( char * )  data . data_ptr ( ) ,  offset ,  & offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        size_t  dataLength  =  data . length ( )  -  offset ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# ifdef PKT_LOG_WHISPER 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        logTrace ( this - > getServerId ( ) ,  " {} Whisper data length: {}. Client count: {}. Channel count: {}. " ,  CLIENT_STR_LOG_PREFIX ,  dataLength ,  clientCount ,  channelCount ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        //Create the packet data
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        char  packetBuffer [ OUT_WHISPER_PKT_OFFSET  +  dataLength ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( offset  <  data . length ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            memcpy ( & packetBuffer [ OUT_WHISPER_PKT_OFFSET ] ,  & data [ offset ] ,  dataLength ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        le2be16 ( vpacketId ,  packetBuffer ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        le2be16 ( this - > getClientId ( ) ,  packetBuffer ,  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        packetBuffer [ 4 ]  =  codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        VoicePacketFlags  flags { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  data  =  pipes : : buffer_view ( packetBuffer ,  OUT_WHISPER_PKT_OFFSET  +  dataLength ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto &  cl  :  this - > server - > getClients ( ) ) {  //Faster?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  speakingClient  =  dynamic_pointer_cast < SpeakingClient > ( cl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! speakingClient  | |  cl  = =  this )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! cl - > currentChannel )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  clientChannelId  =  cl - > currentChannel - > channelId ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  clientId  =  cl - > getClientId ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for ( uint8_t  index  =  0 ;  index  <  clientCount ;  index + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( channelIds [ index ]  = =  clientChannelId )  goto  handleSend ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for ( uint8_t  index  =  0 ;  index  <  channelCount ;  index + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( clientIds [ index ]  = =  clientId )  goto  handleSend ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handleSend : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( speakingClient - > shouldReceiveVoiceWhisper ( _this . lock ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                speakingClient - > send_voice_whisper_packet ( data ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > updateSpeak ( false ,  system_clock : : now ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define TEST_PARM(type) \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								do  { \
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if ( ! cmd [ 0 ] [ key ] . castable < type > ( ) ) \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { findError ( " parameter_invalid " ) ,  " Invalid type for  "  +  key } ; \
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}  while ( false ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								auto  regex_wildcard  =  std : : regex ( " .* " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define S(x) #x 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define HWID_REGEX(name, pattern)                           \ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								auto  regex_hwid_  # # name  =  [ ] ( ) {                              \
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    try  {                                                    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  std : : regex ( pattern ) ;                          \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  catch  ( std : : exception &  ex )  {                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logError ( 0 ,  " Failed to parse regex for  "  S ( name ) ) ;   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }                                                        \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  regex_wildcard ;                                   \
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HWID_REGEX ( windows ,  " ^[a-z0-9]{32},[a-z0-9]{32}$ " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HWID_REGEX ( unix ,  " ^[a-z0-9]{32}$ " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HWID_REGEX ( android ,  " ^[a-z0-9]{16}$ " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								HWID_REGEX ( ios ,  " ^[A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12}$ " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								command_result  SpeakingClient : : handleCommandClientInit ( Command &  cmd )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TIMING_START ( timings ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:40:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        lock_guard < threads : : Mutex >  lock ( this - > server - > join_attempts_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  inetAddr  =  this - > getPeerIp ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( config : : voice : : clientConnectLimit  >  0  & &  this - > server - > join_attempts [ inetAddr ]  +  1  >  config : : voice : : clientConnectLimit ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  command_result { error : : client_join_rate_limit_reached } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:40:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if ( config : : voice : : connectLimit  >  0  & &  this - > server - > join_attempts [ " _ " ]  +  1  >  config : : voice : : connectLimit ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  command_result { error : : server_join_rate_limit_reached } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:40:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        this - > server - > join_attempts [ inetAddr ] + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > server - > join_attempts [ " _ " ] + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " join atmp c " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if ( ! DatabaseHelper : : assignDatabaseId ( this - > server - > getSql ( ) ,  this - > server - > getServerId ( ) ,  _this . lock ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  command_result { error : : vs_critical ,  " Could not assign database id! " } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " db assign   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > server - > getGroupManager ( ) - > enableCache ( this - > getClientDatabaseId ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " gr cache    " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  static  vector < string >  available_parameters  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_nickname " , 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            " client_version " , 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            " client_platform " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_input_muted " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_input_hardware " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_output_hardware " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_output_muted " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_default_channel " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_default_channel_password " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_server_password " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_meta_data " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_version_sign " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_key_offset " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_nickname_phonetic " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_default_token " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_badges=badges " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_badges " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_myteamspeak_id " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_integrations " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_active_integrations_info " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_browser_engine " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_away " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " client_away_message " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " hwid " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " myTeamspeakId " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " acTime " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " userPubKey " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " authSign " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " pubSign " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " pubSignCert " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for ( const  auto &  key  :  cmd [ 0 ] . keys ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( key  = =  " return_code " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  parm_allowed  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto &  _allowed_key  :  available_parameters )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( _allowed_key  = =  key )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                parm_allowed  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( ! parm_allowed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            debugMessage ( this - > getServerId ( ) ,  " {} Tried to insert a not allowed parameter within clientinit (Key: {}, Value: {}) " ,  CLIENT_STR_LOG_PREFIX ,  key , cmd [ key ] . string ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( key  = =  " myTeamspeakId " )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > properties ( ) [ property : : CLIENT_MYTEAMSPEAK_ID ]  =  cmd [ key ] . string ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  if ( key  = =  " acTime " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if ( key  = =  " userPubKey " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if ( key  = =  " authSign " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if ( key  = =  " pubSign " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if ( key  = =  " pubSignCert " )  continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else  if ( key  = =  " client_version "  | |  key  = =  " client_platform " )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for ( auto &  character  :  cmd [ key ] . string ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if ( ! isascii ( character ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    logWarning ( this - > getServerId ( ) ,  " {} Tried to join within an invalid supplied '{}' ({}) " ,  CLIENT_STR_LOG_PREFIX ,  key , cmd [ key ] . string ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  command_result { error : : client_hacked } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  auto  & info  =  property : : info < property : : ClientProperties > ( key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( * info  = =  property : : CLIENT_UNDEFINED )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            logError ( this - > getServerId ( ) ,  " {} Tried to pass a unknown value {}. Please report this, if you're sure that this key should be known! " ,  CLIENT_STR_LOG_PREFIX ,  key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            //return {findError("parameter_invalid"), "Unknown property " + key};
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if ( ! info - > validate_input ( cmd [ key ] . as < string > ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  command_result { error : : parameter_invalid } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > properties ( ) [ info ]  =  cmd [ key ] . as < std : : string > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    debugMessage ( this - > getServerId ( ) ,  " {} Got client init. (HWID: {}) " ,  CLIENT_STR_LOG_PREFIX ,  this - > getHardwareId ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " props apply " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  permissions_list  =  this - > permissionValues ( permission : : PERMTEST_ORDERED ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : b_virtualserver_join_ignore_password , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : b_client_ignore_bans , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : b_client_ignore_vpn , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : i_client_max_clones_uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : i_client_max_clones_ip , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : i_client_max_clones_hwid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : b_client_enforce_valid_hwid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            permission : : b_client_use_reserved_slot 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  permissions  =  map < permission : : PermissionType ,  permission : : PermissionValue > ( permissions_list . begin ( ) ,  permissions_list . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " perm calc 1 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( geoloc : : provider_vpn  & &  permissions [ permission : : b_client_ignore_vpn ]  = =  permNotGranted )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  provider  =  this - > isAddressV4 ( )  ?  geoloc : : provider_vpn - > resolveInfoV4 ( this - > getPeerIp ( ) ,  true )  :  geoloc : : provider_vpn - > resolveInfoV6 ( this - > getPeerIp ( ) ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( provider ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  command_result { error : : server_connect_banned ,  strvar : : transform ( ts : : config : : messages : : kick_vpn ,  strvar : : StringValue { " provider.name " ,  provider - > name } ,  strvar : : StringValue { " provider.website " ,  provider - > side } ) } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( this - > getType ( )  = =  ClientType : : CLIENT_TEAMSPEAK  & &  ( permissions [ permission : : b_client_enforce_valid_hwid ]  = =  permNotGranted  & &  permissions [ permission : : b_client_enforce_valid_hwid ]  = =  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  hwid  =  this - > properties ( ) [ property : : CLIENT_HARDWARE_ID ] . as < string > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ! std : : regex_match ( hwid ,  regex_hwid_windows )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ! std : : regex_match ( hwid ,  regex_hwid_unix )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ! std : : regex_match ( hwid ,  regex_hwid_android )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ! std : : regex_match ( hwid ,  regex_hwid_ios ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  command_result { error : : parameter_invalid ,  config : : messages : : kick_invalid_hardware_id } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " valid hw ip " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  ignorePassword  =  permissions [ permission : : b_virtualserver_join_ignore_password ]  >  0  & &  permissions [ permission : : b_virtualserver_join_ignore_password ]  ! =  permNotGranted ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! ignorePassword ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if ( ! this - > server - > verifyServerPassword ( cmd [ " client_server_password " ] . string ( ) ,  true ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  command_result { error : : server_invalid_password } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  clones_uid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  clones_ip  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  clones_hwid  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  _own_hwid  =  this - > getHardwareId ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > server - > forEachClient ( [ & ] ( const  shared_ptr < ConnectedClient > &  client )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( client - > getExternalType ( )  ! =  CLIENT_TEAMSPEAK )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( client - > getUid ( )  = =  this - > getUid ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            clones_uid + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( client - > getPeerIp ( )  = =  this - > getPeerIp ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            clones_ip + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( client - > getHardwareId ( )  = =  _own_hwid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            clones_hwid + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( permissions [ permission : : i_client_max_clones_uid ]  >  0  & &  clones_uid  > =  permissions [ permission : : i_client_max_clones_uid ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " {} Disconnecting because there are already {} uid clones connected. (Allowed: {}) " ,  CLIENT_STR_LOG_PREFIX ,  clones_uid ,  permissions [ permission : : i_client_max_clones_uid ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  command_result { error : :  client_too_many_clones_connected ,  " too many clones connected (uid) " } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( permissions [ permission : : i_client_max_clones_ip ]  >  0  & &  clones_ip  > =  permissions [ permission : : i_client_max_clones_ip ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " {} Disconnecting because there are already {} ip clones connected. (Allowed: {}) " ,  CLIENT_STR_LOG_PREFIX ,  clones_ip ,  permissions [ permission : : i_client_max_clones_ip ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  command_result { error : :  client_too_many_clones_connected ,  " too many clones connected (ip) " } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( permissions [ permission : : i_client_max_clones_hwid ]  >  0  & &  clones_hwid  > =  permissions [ permission : : i_client_max_clones_hwid ]  & &  ! _own_hwid . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " {} Disconnecting because there are already {} hwid clones connected. (Allowed: {}) " ,  CLIENT_STR_LOG_PREFIX ,  clones_hwid ,  permissions [ permission : : i_client_max_clones_hwid ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  command_result { error : :  client_too_many_clones_connected ,  " too many clones connected (hwid) " } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " max clones  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  banEntry  =  this - > resolveActiveBan ( this - > getPeerIp ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( banEntry )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " {} Disconnecting while init because of ban record. Record id {} at server {} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                CLIENT_STR_LOG_PREFIX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                banEntry - > banId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                banEntry - > serverId ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        serverInstance - > banManager ( ) - > trigger_ban ( banEntry ,  this - > getServerId ( ) ,  this - > getUid ( ) ,  this - > getHardwareId ( ) ,  this - > getDisplayName ( ) ,  this - > getPeerIp ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        string  fullReason  =  string ( )  +  " You are banned  "  +  ( banEntry - > serverId  = =  0  ?  " globally "  :  " from this server " )  +  " . Reason:  \" "  +  banEntry - > reason  +  " \" . Ban expires  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        string  time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( banEntry - > until . time_since_epoch ( ) . count ( )  ! =  0 ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            time  + =  " in  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  seconds  =  chrono : : ceil < chrono : : seconds > ( banEntry - > until  -  chrono : : system_clock : : now ( ) ) . count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            tm  p { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            memset ( & p ,  0 ,  sizeof ( p ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            while ( seconds  > =  365  *  24  *  60  *  60 ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                p . tm_year + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                seconds  - =  365  *  24  *  60  *  60 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            while ( seconds  > =  24  *  60  *  60 ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                p . tm_yday + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                seconds  - =  24  *  60  *  60 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            while ( seconds  > =  60  *  60 ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                p . tm_hour + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                seconds  - =  60  *  60 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            while ( seconds  > =  60 ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                p . tm_min + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                seconds  - =  60 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            p . tm_sec  =  ( int )  seconds ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( p . tm_year  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                time  + =  to_string ( p . tm_year )  +  "  years,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( p . tm_yday  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                time  + =  to_string ( p . tm_yday )  +  "  days,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( p . tm_hour  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                time  + =  to_string ( p . tm_hour )  +  "  hours,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( p . tm_min  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                time  + =  to_string ( p . tm_min )  +  "  minutes,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( p . tm_sec  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                time  + =  to_string ( p . tm_sec )  +  "  seconds,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( time . empty ( ) )  time  =  " now,  " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            time  =  time . substr ( 0 ,  time . length ( )  -  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  time  =  " never " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        fullReason  + =  time  +  " ! " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  command_result { error : : server_connect_banned ,  fullReason } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " ban resolve " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for ( const  auto  & cl  :  this - > server - > getClients ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ( cl - > getType ( )  = =  CLIENT_TEAMSPEAK  | |  cl - > getType ( )  = =  CLIENT_WEB  | |  cl - > getType ( )  = =  CLIENT_TEASPEAK  | |  cl - > getType ( )  = =  CLIENT_MUSIC ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if ( cl - > connectionState ( )  < =  ConnectionState : : CONNECTED  & &  cl - > connectionState ( )  > =  ConnectionState : : INIT_HIGH ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    count + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  maxClients  =  this - > server - > properties ( ) [ property : : VIRTUALSERVER_MAXCLIENTS ] . as < size_t > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  reserved  =  this - > server - > properties ( ) [ property : : VIRTUALSERVER_RESERVED_SLOTS ] . as < size_t > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  allowReserved  =  permissions [ permission : : b_client_use_reserved_slot ]  ! =  permNotGranted  & &  permissions [ permission : : b_client_use_reserved_slot ]  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( reserved  >  maxClients ) { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if ( ! allowReserved ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  command_result { error : : server_maxclients_reached } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  if ( maxClients  -  ( allowReserved  ?  0  :  reserved )  < =  count ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  command_result { error : : server_maxclients_reached } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " max clients " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  old_last_connected  =  this - > properties ( ) [ property : : CLIENT_LASTCONNECTED ] . as < int64_t > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > properties ( ) [ property : : CONNECTION_CLIENT_IP ]  =  this - > getLoggingPeerIp ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > properties ( ) [ property : : CLIENT_LASTCONNECTED ]  =  std : : chrono : : duration_cast < std : : chrono : : seconds > ( std : : chrono : : system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > properties ( ) [ property : : CLIENT_TOTALCONNECTIONS ] + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  time_point  =  system_clock : : time_point ( )  +  seconds ( old_last_connected ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( time_point  <  build : : version ( ) - > timestamp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            logMessage ( this - > getServerId ( ) ,  " {} Client may cached a old permission list (Server is newer than the client's last join) " ,  CLIENT_STR_LOG_PREFIX ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TIMING_STEP ( timings ,  " pre dummy p " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Command  _dummy ( " dummy_permissionslist " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > handleCommandPermissionList ( _dummy ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TIMING_STEP ( timings ,  " pst dummy p " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > postCommandHandler . emplace_back ( [ & ] ( ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  self  =  dynamic_pointer_cast < SpeakingClient > ( _this . lock ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        std : : thread ( [ self ] ( ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            threads : : MutexLock  l1 ( self - > disconnectLock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( self - > state  ! =  ConnectionState : : INIT_HIGH )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                self - > processJoin ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  catch  ( std : : exception &  ex )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                logError ( self - > getServerId ( ) ,  " Failed to proceed client join for {}. Got exception with message {} " ,  CLIENT_STR_LOG_PREFIX_ ( self ) ,  ex . what ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                self - > closeConnection ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ) . detach ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    debugMessage ( this - > getServerId ( ) ,  " {} Client init timings: {} " ,  CLIENT_STR_LOG_PREFIX ,  TIMING_FINISH ( timings ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  command_result { error : : ok } ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* must be triggered while helding an execute lock */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								//Note: Client permissions are may not really
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : processJoin ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TIMING_START ( timings ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  ref_server  =  this - > server ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > resetIdleTime ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    threads : : MutexLock  lock ( this - > command_lock ) ;  //Don't process any commands!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( this - > state  ! =  ConnectionState : : INIT_HIGH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logError ( this - > getServerId ( ) ,  " {} Invalid processJoin() connection state! " ,  CLIENT_STR_LOG_PREFIX ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " setup       " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ref_server - > registerClient ( _this . lock ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " server reg  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ref_server - > getGroupManager ( ) - > cleanupAssignments ( this - > getClientDatabaseId ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " grp cleanup " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ref_server - > getGroupManager ( ) - > update_server_group_property ( _this . lock ( ) ,  true ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " grp apply   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > properties ( ) [ property : : CLIENT_COUNTRY ]  =  config : : geo : : countryFlag ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( geoloc : : provider )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  loc  =  this - > isAddressV4 ( )  ?  geoloc : : provider - > resolveInfoV4 ( this - > getPeerIp ( ) ,  false )  :  geoloc : : provider - > resolveInfoV6 ( this - > getPeerIp ( ) ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( loc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            debugMessage ( this - > getServerId ( ) ,  " Client  "  +  this - > getDisplayName ( )  +  " | "  +  this - > getLoggingPeerIp ( )  +  "  comes from  "  +  loc - > name  +  " | "  +  loc - > identifier ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > properties ( ) [ property : : CLIENT_COUNTRY ]  =  loc - > identifier ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            logError ( ref_server  ?  ref_server - > getServerId ( )  :  0 ,  " Could not resolve country for ip  "  +  this - > getLoggingPeerIp ( )  +  " | "  +  this - > getDisplayName ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //this->updateChannelClientProperties(false); /* will be already updated via assignChannel */
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ref_server - > properties ( ) [ property : : VIRTUALSERVER_HOSTMESSAGE_MODE ] . as < int > ( )  = =  3  & &  ! ref_server - > properties ( ) [ property : : VIRTUALSERVER_HOSTMESSAGE ] . as < string > ( ) . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  weak  =  this - > _this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        threads : : Thread ( [ weak ] ( ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            threads : : self : : sleep_for ( milliseconds ( 2000 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  client  =  weak . lock ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! client  | |  ! client - > server )  return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            client - > disconnect ( client - > server - > properties ( ) [ property : : VIRTUALSERVER_HOSTMESSAGE ] . as < string > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ) . detach ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " ip 2 loc as " ) ;  //IP to location assignment
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > sendServerInit ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    debugMessage ( this - > getServerId ( ) ,  " Client id:  "  +  to_string ( this - > getClientId ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " notify sini " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! ref_server - > assignDefaultChannel ( this - > ref ( ) ,  false ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        auto  result  =  command_result { error : : vs_critical ,  " Could not assign default channel! " } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > notifyError ( result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        result . release_details ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        this - > closeConnection ( system_clock : : now ( )  +  seconds ( 1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " assign chan " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > sendChannelList ( true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > state  =  ConnectionState : : CONNECTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " send chan t " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* trick the join method */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  channel  =  this - > currentChannel ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > currentChannel  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* enforce an update of these properties */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > properties ( ) [ property : : CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID ]  =  " 0 " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > properties ( ) [ property : : CLIENT_CHANNEL_GROUP_ID ]  =  " 0 " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > properties ( ) [ property : : CLIENT_TALK_POWER ]  =  " 0 " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        unique_lock  server_channel_lock ( this - > server - > channel_tree_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > server - > client_move ( this - > ref ( ) ,  channel ,  nullptr ,  " " ,  ViewReasonId : : VREASON_USER_ACTION ,  false ,  server_channel_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > subscribeChannel ( { this - > currentChannel } ,  false ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " join move   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > properties ( ) - > triggerAllModified ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > notifyServerGroupList ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > notifyChannelGroupList ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TIMING_STEP ( timings ,  " notify grou " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    logMessage ( this - > getServerId ( ) ,  " Voice client {}/{} ({}) from {} joined. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > getClientDatabaseId ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > getUid ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > getDisplayName ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > getLoggingPeerIp ( )  +  " : "  +  to_string ( this - > getPeerPort ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > connectTimestamp  =  chrono : : system_clock : : now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > idleTimestamp  =  chrono : : system_clock : : now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    debugMessage ( this - > getServerId ( ) ,  " {} Client join timings: {} " ,  CLIENT_STR_LOG_PREFIX ,  TIMING_FINISH ( timings ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : processLeave ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  ownLock  =  _this . lock ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  server  =  this - > getServer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( server ) { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        logMessage ( this - > getServerId ( ) ,  " Voice client {}/{} ({}) from {} left. " ,  this - > getClientDatabaseId ( ) ,  this - > getUid ( ) ,  this - > getDisplayName ( ) ,  this - > getLoggingPeerIp ( )  +  " : "  +  to_string ( this - > getPeerPort ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            unique_lock  server_channel_lock ( this - > server - > channel_tree_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            server - > unregisterClient ( ownLock ,  " disconnected " ,  server_channel_lock ) ;  /* already moves client to void if needed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        server - > groups - > disableCache ( ownLock - > getClientDatabaseId ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        server - > musicManager - > cleanup_client_bots ( this - > getClientDatabaseId ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //ref_server = nullptr; Removed caused nullptr exceptions
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    {    //Delete own viewing clients
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  No  need ,  are  only  weak  references ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        threads : : MutexLock  l ( this - > viewLock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > visibleClients . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > mutedClients . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : triggerVoiceEnd ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    this - > properties ( ) [ property : : CLIENT_FLAG_TALKING ]  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : updateSpeak ( bool  onlyUpdate ,  const  std : : chrono : : system_clock : : time_point  & now )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    threads : : MutexLock  lock ( this - > speak_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( this - > speak_last_packet  +  this - > speak_accuracy  <  now )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( this - > speak_last_packet  >  this - > speak_begin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( ! this - > properties ( ) [ property : : CLIENT_FLAG_TALKING ] . as < bool > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this - > properties ( ) [ property : : CLIENT_FLAG_TALKING ]  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            this - > speak_time  + =  duration_cast < milliseconds > ( this - > speak_last_packet  -  this - > speak_begin ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( this - > properties ( ) [ property : : CLIENT_FLAG_TALKING ] . as < bool > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this - > properties ( ) [ property : : CLIENT_FLAG_TALKING ]  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > speak_begin  =  now ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > speak_last_packet  =  now ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( ! onlyUpdate ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        this - > speak_last_packet  =  now ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : tick ( const  std : : chrono : : system_clock : : time_point  & time )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ConnectedClient : : tick ( time ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ALARM_TIMER ( A1 ,  " SpeakingClient::tick " ,  milliseconds ( 2 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > updateSpeak ( true ,  time ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if ( this - > state  = =  ConnectionState : : CONNECTED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( this - > max_idle_time . has_value )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  max_idle  =  this - > max_idle_time . value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if ( max_idle  >  0  & &  this - > idleTimestamp . time_since_epoch ( ) . count ( )  >  0  & &  duration_cast < seconds > ( time  -  this - > idleTimestamp ) . count ( )  >  max_idle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this - > server - > notify_client_kick ( this - > ref ( ) ,  this - > server - > getServerRoot ( ) ,  ts : : config : : messages : : idle_time_exceeded ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this - > closeConnection ( system_clock : : now ( )  +  seconds ( 1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  SpeakingClient : : updateChannelClientProperties ( bool  channel_lock ,  bool  notify )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ConnectedClient : : updateChannelClientProperties ( channel_lock ,  notify ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > max_idle_time  =  this - > permissionValueFlagged ( permission : : i_client_max_idletime ,  this - > currentChannel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								command_result  SpeakingClient : : handleCommand ( Command  & command )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if ( this - > connectionState ( )  = =  ConnectionState : : INIT_HIGH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if ( this - > handshake . state  = =  HandshakeState : : BEGIN  | |  this - > handshake . state  = =  HandshakeState : : IDENTITY_PROOF )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            command_result  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if ( command . command ( )  = =  " handshakebegin " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  this - > handleCommandHandshakeBegin ( command ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else  if ( command . command ( )  = =  " handshakeindentityproof " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  this - > handleCommandHandshakeIdentityProof ( command ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                result  =  command_result { error : : client_not_logged_in } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-25 23:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if ( result . error_code ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                this - > postCommandHandler . push_back ( [ & ] { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    this - > closeConnection ( system_clock : : now ( )  +  seconds ( 1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-24 02:57:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ConnectedClient : : handleCommand ( command ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-17 19:37:18 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}