2019-07-17 13:37:18 -04:00
# pragma once
2020-02-21 14:32:25 -05:00
# include <teaspeak/MusicPlayer.h>
2019-07-17 13:37:18 -04:00
# include <misc/net.h>
# include <cstdint>
2020-02-02 08:58:46 -05:00
# include <src/music/PlayablePlaylist.h>
2019-07-17 13:37:18 -04:00
# include "music/Song.h"
# include "../channel/ClientChannelView.h"
# include "DataClient.h"
2020-01-26 08:21:34 -05:00
# include "query/command3.h"
2019-07-17 13:37:18 -04:00
# define CLIENT_STR_LOG_PREFIX_(this) (std::string("[") + this->getLoggingPeerIp() + ":" + std::to_string(this->getPeerPort()) + " / " + this->getDisplayName() + " | " + std::to_string(this->getClientId()) + "]")
# define CLIENT_STR_LOG_PREFIX CLIENT_STR_LOG_PREFIX_(this)
# define CMD_REQ_SERVER \
2020-05-13 05:32:08 -04:00
do { \
if ( ! this - > server ) { \
return command_result { error : : server_invalid_id } ; \
} \
} while ( 0 )
2019-07-17 13:37:18 -04:00
/* TODO: Play lock the server here with read? So the client dosn't get kicked within that moment */
# define CMD_REF_SERVER(variable_name) \
2020-01-26 12:04:38 -05:00
std : : shared_ptr < VirtualServer > variable_name = this - > getServer ( ) ; \
2020-01-25 17:42:37 -05:00
if ( ! variable_name ) return command_result { error : : server_invalid_id } ;
2019-07-17 13:37:18 -04:00
# define CMD_REQ_CHANNEL \
2020-01-25 17:42:37 -05:00
if ( ! this - > currentChannel ) return command_result { error : : channel_invalid_id } ;
2019-07-17 13:37:18 -04:00
# define CMD_RESET_IDLE \
do { \
2020-01-23 20:57:58 -05:00
this - > resetIdleTime ( ) ; \
2019-07-17 13:37:18 -04:00
} while ( false )
# define CMD_REQ_PARM(parm) \
2020-01-25 17:42:37 -05:00
if ( ! cmd [ 0 ] . has ( parm ) ) return command_result { error : : parameter_not_found } ;
2019-07-17 13:37:18 -04:00
//the message here is show to the manager!
# define CMD_CHK_AND_INC_FLOOD_POINTS(num) \
2020-05-13 05:32:08 -04:00
do { \
this - > increaseFloodPoints ( num ) ; \
if ( this - > shouldFloodBlock ( ) ) return command_result { error : : ban_flooding } ; \
} while ( 0 )
2019-07-17 13:37:18 -04:00
# define CMD_CHK_PARM_COUNT(count) \
2020-01-25 17:42:37 -05:00
if ( cmd . bulkCount ( ) ! = count ) return command_result { error : : parameter_invalid_count } ;
2019-07-17 13:37:18 -04:00
namespace ts {
2020-01-23 20:57:58 -05:00
class GroupManager ;
2019-07-17 13:37:18 -04:00
namespace connection {
class VoiceClientConnection ;
}
namespace server {
2020-01-26 12:04:38 -05:00
class VirtualServer ;
2019-07-17 13:37:18 -04:00
class MusicClient ;
class WebClient ;
2020-01-23 20:57:58 -05:00
class MusicClient ;
2019-07-17 13:37:18 -04:00
struct ConnectionInfoData {
std : : chrono : : time_point < std : : chrono : : system_clock > timestamp ;
std : : map < std : : string , std : : string > properties ;
} ;
class ConnectedClient : public DataClient {
2020-01-26 12:04:38 -05:00
friend class VirtualServer ;
2019-07-17 13:37:18 -04:00
friend class VoiceServer ;
friend class VoiceClient ;
friend class MusicClient ;
friend class WebClient ;
friend class WebControlServer ;
friend class music : : MusicBotManager ;
friend class QueryServer ;
friend class DataClient ;
friend class SpeakingClient ;
friend class connection : : VoiceClientConnection ;
friend class ts : : GroupManager ;
2020-01-26 20:21:39 -05:00
friend class VirtualServerManager ;
2019-07-17 13:37:18 -04:00
public :
2020-01-26 12:04:38 -05:00
explicit ConnectedClient ( sql : : SqlManager * , const std : : shared_ptr < VirtualServer > & server ) ;
2019-07-17 13:37:18 -04:00
~ ConnectedClient ( ) override ;
ConnectionState connectionState ( ) { return this - > state ; }
std : : string getLoggingPeerIp ( ) { return config : : server : : disable_ip_saving | | ( this - > server & & this - > server - > disable_ip_saving ( ) ) ? " X.X.X.X " : this - > getPeerIp ( ) ; }
std : : string getPeerIp ( ) { return this - > isAddressV4 ( ) ? net : : to_string ( this - > getAddressV4 ( ) - > sin_addr ) : this - > isAddressV6 ( ) ? net : : to_string ( this - > getAddressV6 ( ) - > sin6_addr ) : " localhost " ; }
uint16_t getPeerPort ( ) { return ntohs ( this - > isAddressV4 ( ) ? this - > getAddressV4 ( ) - > sin_port : this - > isAddressV6 ( ) ? this - > getAddressV6 ( ) - > sin6_port : ( uint16_t ) 0 ) ; }
std : : string getHardwareId ( ) { return properties ( ) [ property : : CLIENT_HARDWARE_ID ] ; }
//General connection stuff
2020-01-23 20:57:58 -05:00
bool isAddressV4 ( ) { return this - > remote_address . ss_family = = AF_INET ; }
2019-07-17 13:37:18 -04:00
const sockaddr_in * getAddressV4 ( ) { return ( sockaddr_in * ) & this - > remote_address ; }
2020-01-23 20:57:58 -05:00
bool isAddressV6 ( ) { return this - > remote_address . ss_family = = AF_INET6 ; }
const sockaddr_in6 * getAddressV6 ( ) { return ( sockaddr_in6 * ) & this - > remote_address ; }
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
/* Note: Order is not guaranteed here! */
2019-07-17 13:37:18 -04:00
virtual void sendCommand ( const ts : : Command & command , bool low = false ) = 0 ;
2020-01-26 08:21:34 -05:00
virtual void sendCommand ( const ts : : command_builder & command , bool low = false ) = 0 ;
2019-07-17 13:37:18 -04:00
//General manager stuff
//FIXME cache the client id for speedup
virtual uint16_t getClientId ( ) { return this - > properties ( ) [ property : : CLIENT_ID ] ; }
virtual void setClientId ( uint16_t clId ) { properties ( ) [ property : : CLIENT_ID ] = clId ; }
2020-01-23 20:57:58 -05:00
inline std : : shared_ptr < BasicChannel > getChannel ( ) { return this - > currentChannel ; }
2020-01-26 08:21:34 -05:00
inline ChannelId getChannelId ( ) { auto channel = this - > currentChannel ; return channel ? channel - > channelId ( ) : 0 ; }
2020-01-26 12:04:38 -05:00
inline std : : shared_ptr < VirtualServer > getServer ( ) { return this - > server ; }
2020-01-23 20:57:58 -05:00
inline ServerId getServerId ( ) { return this - > server ? this - > server - > getServerId ( ) : ( ServerId ) 0 ; }
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
//bool channelSubscribed(const std::shared_ptr<BasicChannel>&);
/* if lock_channel == false then channel_lock must be write locked! */
2019-07-17 13:37:18 -04:00
std : : deque < std : : shared_ptr < BasicChannel > > subscribeChannel ( const std : : deque < std : : shared_ptr < BasicChannel > > & target , bool lock_channel , bool /* enforce */ ) ;
2020-01-23 20:57:58 -05:00
/* if lock_channel == false then channel_lock must be write locked! */
2019-07-17 13:37:18 -04:00
std : : deque < std : : shared_ptr < BasicChannel > > unsubscribeChannel ( const std : : deque < std : : shared_ptr < BasicChannel > > & target , bool lock_channel ) ;
bool isClientVisible ( const std : : shared_ptr < ConnectedClient > & , bool /* lock channel lock */ ) ;
inline std : : deque < std : : weak_ptr < ConnectedClient > > getVisibleClients ( bool lock_channel ) {
2020-01-23 20:57:58 -05:00
std : : shared_lock lock ( this - > channel_lock , std : : defer_lock ) ;
if ( lock_channel )
lock . lock ( ) ;
return this - > visibleClients ;
2019-07-17 13:37:18 -04:00
}
/** Notifies general stuff **/
2020-01-25 17:42:37 -05:00
virtual bool notifyError ( const command_result & , const std : : string & retCode = " " ) ;
2020-07-13 05:13:09 -04:00
virtual void writeCommandResult ( ts : : command_builder & , const command_result & , const std : : string & errorCodeKey = " id " ) ;
2019-07-17 13:37:18 -04:00
/** Notifies (after request) */
bool sendNeededPermissions ( bool /* force an update */ ) ; /* invoke this because it dosn't spam the client */
virtual bool notifyClientNeededPermissions ( ) ;
2020-11-07 07:17:51 -05:00
virtual bool notifyServerGroupList ( bool as_notify = true ) ;
2019-07-17 13:37:18 -04:00
virtual bool notifyGroupPermList ( const std : : shared_ptr < Group > & , bool ) ;
virtual bool notifyClientPermList ( ClientDbId , const std : : shared_ptr < permission : : v2 : : PermissionManager > & , bool ) ;
2020-11-07 07:17:51 -05:00
virtual bool notifyChannelGroupList ( bool as_notify = true ) ;
2019-08-25 16:16:42 -04:00
virtual bool notifyConnectionInfo ( const std : : shared_ptr < ConnectedClient > & target , const std : : shared_ptr < ConnectionInfoData > & info ) ;
2019-07-17 13:37:18 -04:00
virtual bool notifyChannelSubscribed ( const std : : deque < std : : shared_ptr < BasicChannel > > & ) ;
virtual bool notifyChannelUnsubscribed ( const std : : deque < std : : shared_ptr < BasicChannel > > & ) ;
/** Notifies (without request) */
//Group server
virtual bool notifyServerUpdated ( std : : shared_ptr < ConnectedClient > ) ;
//Group manager
virtual bool notifyClientPoke ( std : : shared_ptr < ConnectedClient > invoker , std : : string msg ) ;
virtual bool notifyClientUpdated (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < ConnectedClient > & ,
2020-04-08 07:01:41 -04:00
const std : : deque < const property : : PropertyDescription * > & ,
2019-07-17 13:37:18 -04:00
bool lock_channel_tree
) ; /* invalid client id causes error: invalid clientID */
virtual bool notifyPluginCmd ( std : : string name , std : : string msg , std : : shared_ptr < ConnectedClient > ) ;
//Group manager chat
virtual bool notifyClientChatComposing ( const std : : shared_ptr < ConnectedClient > & ) ;
virtual bool notifyClientChatClosed ( const std : : shared_ptr < ConnectedClient > & ) ;
2019-08-20 07:46:23 -04:00
virtual bool notifyTextMessage ( ChatMessageMode mode , const std : : shared_ptr < ConnectedClient > & sender , uint64_t targetId , ChannelId channel_id , const std : : chrono : : system_clock : : time_point & /* timestamp */ , const std : : string & textMessage ) ;
2019-07-17 13:37:18 -04:00
inline void sendChannelMessage ( const std : : shared_ptr < ConnectedClient > & sender , const std : : string & textMessage ) {
2020-01-23 20:57:58 -05:00
this - > notifyTextMessage ( ChatMessageMode : : TEXTMODE_CHANNEL , sender , this - > currentChannel ? this - > currentChannel - > channelId ( ) : 0 , 0 , std : : chrono : : system_clock : : now ( ) , textMessage ) ;
2019-07-17 13:37:18 -04:00
}
//Group Client Groups
virtual bool notifyServerGroupClientAdd ( const std : : shared_ptr < ConnectedClient > & invoker , const std : : shared_ptr < ConnectedClient > & client , const std : : shared_ptr < Group > & group ) ;
virtual bool notifyServerGroupClientRemove ( std : : shared_ptr < ConnectedClient > invoker , std : : shared_ptr < ConnectedClient > client , std : : shared_ptr < Group > group ) ;
2020-01-23 20:57:58 -05:00
/* invalid client id causes error: invalid clientID */
/* invalid channel id causes error: invalid channelID */
/* an invalid channel or not a client's channel causes: invalid channelID */
2019-07-17 13:37:18 -04:00
virtual bool notifyClientChannelGroupChanged (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < ConnectedClient > & invoker ,
const std : : shared_ptr < ConnectedClient > & client ,
const std : : shared_ptr < BasicChannel > & /*channel*/ ,
2019-07-17 13:37:18 -04:00
const std : : shared_ptr < BasicChannel > & /*inherited channel*/ ,
const std : : shared_ptr < Group > & group ,
bool lock_channel_tree /* server channel tree AND client tree must be at least read locked! */
) ;
//Group channel
virtual bool notifyChannelMoved ( const std : : shared_ptr < BasicChannel > & channel , ChannelId order , const std : : shared_ptr < ConnectedClient > & invoker ) ;
virtual bool notifyChannelDescriptionChanged ( std : : shared_ptr < BasicChannel > channel ) ;
virtual bool notifyChannelPasswordChanged ( std : : shared_ptr < BasicChannel > ) ;
2019-11-10 12:31:40 -05:00
virtual bool notifyChannelEdited (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < BasicChannel > & /* channel */ ,
2019-11-10 12:31:40 -05:00
const std : : vector < property : : ChannelProperties > & /* properties */ ,
const std : : shared_ptr < ConnectedClient > & /* invoker */ ,
bool /* send channel description */
) ; /* clients channel tree must be at least read locked */
2019-07-17 13:37:18 -04:00
virtual bool notifyChannelHide ( const std : : deque < ChannelId > & channels , bool lock_channel_tree ) ;
virtual bool notifyChannelShow ( const std : : shared_ptr < BasicChannel > & channel , ChannelId orderId ) ; /* client channel tree must be unique locked and server channel tree shared locked */
virtual bool notifyChannelCreate ( const std : : shared_ptr < BasicChannel > & channel , ChannelId orderId , const std : : shared_ptr < ConnectedClient > & invoker ) ;
virtual bool notifyChannelDeleted ( const std : : deque < ChannelId > & /* channel_ids */ , const std : : shared_ptr < ConnectedClient > & /* invoker */ ) ;
//Client view
virtual bool notifyClientEnterView (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < ConnectedClient > & client ,
const std : : shared_ptr < ConnectedClient > & invoker ,
const std : : string & /* reason */ ,
const std : : shared_ptr < BasicChannel > & to ,
ViewReasonId reasonId ,
const std : : shared_ptr < BasicChannel > & from ,
bool lock_channel_tree
2019-07-17 13:37:18 -04:00
) ;
2020-01-23 20:57:58 -05:00
virtual bool notifyClientEnterView ( const std : : deque < std : : shared_ptr < ConnectedClient > > & /* clients */ , const ViewReasonSystemT & /* mode */ ) ; /* channel lock must be write locked */
virtual bool notifyClientMoved (
const std : : shared_ptr < ConnectedClient > & client ,
const std : : shared_ptr < BasicChannel > & target_channel ,
ViewReasonId reason ,
std : : string msg ,
2019-07-17 13:37:18 -04:00
std : : shared_ptr < ConnectedClient > invoker ,
2020-01-23 20:57:58 -05:00
bool lock_channel_tree
) ;
virtual bool notifyClientLeftView (
const std : : shared_ptr < ConnectedClient > & client ,
const std : : shared_ptr < BasicChannel > & target_channel ,
ViewReasonId reasonId ,
const std : : string & reasonMessage ,
std : : shared_ptr < ConnectedClient > invoker ,
bool lock_channel_tree
2019-07-17 13:37:18 -04:00
) ;
virtual bool notifyClientLeftView (
2020-01-23 20:57:58 -05:00
const std : : deque < std : : shared_ptr < ConnectedClient > > & /* clients */ ,
const std : : string & /* reason */ ,
bool /* lock channel view */ ,
const ViewReasonServerLeftT & /* mode */
2019-07-17 13:37:18 -04:00
) ;
virtual bool notifyClientLeftViewKicked (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < ConnectedClient > & client ,
const std : : shared_ptr < BasicChannel > & target_channel ,
const std : : string & message ,
std : : shared_ptr < ConnectedClient > invoker ,
bool lock_channel_tree
2019-07-17 13:37:18 -04:00
) ;
virtual bool notifyClientLeftViewBanned (
2020-01-23 20:57:58 -05:00
const std : : shared_ptr < ConnectedClient > & client ,
const std : : string & message ,
std : : shared_ptr < ConnectedClient > invoker ,
size_t length ,
bool lock_channel_tree
2019-07-17 13:37:18 -04:00
) ;
2020-01-23 20:57:58 -05:00
virtual bool notifyMusicPlayerSongChange ( const std : : shared_ptr < MusicClient > & bot , const std : : shared_ptr < music : : SongInfo > & newEntry ) ;
virtual bool notifyMusicQueueAdd ( const std : : shared_ptr < MusicClient > & bot , const std : : shared_ptr < ts : : music : : SongInfo > & entry , int index , const std : : shared_ptr < ConnectedClient > & invoker ) ;
virtual bool notifyMusicQueueRemove ( const std : : shared_ptr < MusicClient > & bot , const std : : deque < std : : shared_ptr < music : : SongInfo > > & entry , const std : : shared_ptr < ConnectedClient > & invoker ) ;
virtual bool notifyMusicQueueOrderChange ( const std : : shared_ptr < MusicClient > & bot , const std : : shared_ptr < ts : : music : : SongInfo > & entry , int order , const std : : shared_ptr < ConnectedClient > & invoker ) ;
virtual bool notifyMusicPlayerStatusUpdate ( const std : : shared_ptr < MusicClient > & ) ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
virtual bool notifyConversationMessageDelete ( const ChannelId /* conversation id */ , const std : : chrono : : system_clock : : time_point & /* begin timestamp */ , const std : : chrono : : system_clock : : time_point & /* begin end */ , ClientDbId /* client id */ , size_t /* messages */ ) ;
2019-08-20 07:46:23 -04:00
2020-02-01 08:32:16 -05:00
/* this method should be callable from everywhere; the method is non blocking! */
virtual bool close_connection ( const std : : chrono : : system_clock : : time_point & timeout ) = 0 ;
/* this method should be callable from everywhere; the method is non blocking! */
2019-07-17 13:37:18 -04:00
virtual bool disconnect ( const std : : string & reason ) = 0 ;
void resetIdleTime ( ) ;
void increaseFloodPoints ( uint16_t ) ;
bool shouldFloodBlock ( ) ;
2020-01-23 20:57:58 -05:00
virtual bool ignoresFlood ( ) { return ! this - > block_flood ; }
2019-08-25 16:16:42 -04:00
std : : shared_ptr < ConnectionInfoData > request_connection_info ( const std : : shared_ptr < ConnectedClient > & /* receiver */ , bool & /* send temporary (no client response yet) */ ) ;
2019-07-17 13:37:18 -04:00
virtual void updateChannelClientProperties ( bool /* lock channel tree */ , bool /* notify our self */ ) ;
2020-07-28 12:36:32 -04:00
void updateTalkRights ( permission : : v2 : : PermissionFlaggedValue talk_power ) ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
virtual std : : shared_ptr < BanRecord > resolveActiveBan ( const std : : string & ip_address ) ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
inline std : : shared_ptr < stats : : ConnectionStatistics > getConnectionStatistics ( ) {
return this - > connectionStatistics ;
}
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
inline std : : shared_ptr < ClientChannelView > channel_view ( ) { return this - > channels ; }
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
inline std : : shared_ptr < ConnectedClient > ref ( ) { return _this . lock ( ) ; }
2019-07-17 13:37:18 -04:00
2020-02-01 08:32:16 -05:00
std : : shared_mutex & get_channel_lock ( ) { return this - > channel_lock ; }
2020-01-23 20:57:58 -05:00
/*
* permission stuff
*/
2020-01-26 08:21:34 -05:00
/*
2020-01-23 20:57:58 -05:00
inline permission : : PermissionValue cached_permission_value ( permission : : PermissionType type ) const {
std : : lock_guard lock ( this - > cached_permissions_lock ) ;
auto index = this - > cached_permissions . find ( type ) ;
if ( index ! = this - > cached_permissions . end ( ) )
return index - > second ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
We ' re only caching permissions which are granted to reduce memory
2020-01-23 20:57:58 -05:00
//logError(this->getServerId(), "{} Looked up cached permission, which hasn't been cached!", CLIENT_STR_LOG_PREFIX);
return permNotGranted ;
}
2020-01-26 08:21:34 -05:00
*/
2020-01-23 20:57:58 -05:00
bool update_cached_permissions ( ) ;
2020-02-01 08:32:16 -05:00
std : : shared_lock < std : : shared_mutex > require_connected_state ( bool blocking = false ) {
//try_to_lock_t
std : : shared_lock < std : : shared_mutex > disconnect_lock { } ;
2020-02-16 06:38:49 -05:00
if ( blocking ) [ [ unlikely ] ]
2020-02-01 08:32:16 -05:00
disconnect_lock = std : : shared_lock { this - > finalDisconnectLock } ;
else
disconnect_lock = std : : shared_lock { this - > finalDisconnectLock , std : : try_to_lock } ;
2020-02-16 06:38:49 -05:00
if ( ! disconnect_lock ) [ [ unlikely ] ]
2020-02-01 08:32:16 -05:00
return disconnect_lock ;
{
std : : lock_guard state_lock { this - > state_lock } ;
if ( this - > state ! = ConnectionState : : CONNECTED )
return { } ;
}
return disconnect_lock ;
}
2020-02-02 08:58:46 -05:00
inline bool playlist_subscribed ( const std : : shared_ptr < ts : : music : : Playlist > & playlist ) const {
return this - > _subscribed_playlist . lock ( ) = = playlist ;
}
2019-07-17 13:37:18 -04:00
protected :
std : : weak_ptr < ConnectedClient > _this ;
2020-02-01 08:32:16 -05:00
sockaddr_storage remote_address ;
2019-07-17 13:37:18 -04:00
//General states
std : : mutex state_lock ;
2020-02-01 08:32:16 -05:00
ConnectionState state { ConnectionState : : UNKNWON } ;
2019-07-17 13:37:18 -04:00
bool allowedToTalk = false ;
2020-02-01 08:32:16 -05:00
std : : shared_mutex finalDisconnectLock ; /* locked before state lock! */
2019-07-17 13:37:18 -04:00
std : : vector < GroupId > cached_server_groups { } ; /* variable locked with channel_lock */
2020-01-23 20:57:58 -05:00
GroupId cached_channel_group = 0 ; /* variable locked with channel_lock */
2019-07-17 13:37:18 -04:00
std : : deque < std : : weak_ptr < ConnectedClient > > visibleClients { } ; /* variable locked with channel_lock */
std : : deque < std : : weak_ptr < ConnectedClient > > mutedClients { } ; /* variable locked with channel_lock */
2020-01-23 20:57:58 -05:00
std : : deque < std : : weak_ptr < ConnectedClient > > openChats { } ; /* variable locked with channel_lock */
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
std : : chrono : : system_clock : : time_point lastNeededNotify ;
2019-07-17 13:37:18 -04:00
std : : shared_ptr < BasicChannel > lastNeededPermissionNotifyChannel = nullptr ;
bool requireNeededPermissionResend = false ;
2020-01-23 20:57:58 -05:00
std : : chrono : : system_clock : : time_point connectTimestamp ;
2019-07-17 13:37:18 -04:00
std : : chrono : : system_clock : : time_point lastOnlineTimestamp ;
2020-01-23 20:57:58 -05:00
std : : chrono : : system_clock : : time_point lastTransfareTimestamp ;
std : : chrono : : system_clock : : time_point idleTimestamp ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
struct {
std : : mutex lock ;
std : : shared_ptr < ConnectionInfoData > data ;
std : : chrono : : system_clock : : time_point data_age ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
std : : deque < std : : weak_ptr < ConnectedClient > > receiver ;
std : : chrono : : system_clock : : time_point last_requested ;
} connection_info ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
struct {
std : : chrono : : system_clock : : time_point servergrouplist ;
std : : chrono : : system_clock : : time_point channelgrouplist ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
std : : chrono : : system_clock : : time_point last_notify ;
std : : chrono : : milliseconds notify_timeout = std : : chrono : : seconds ( 60 ) ;
} command_times ;
2019-07-17 13:37:18 -04:00
std : : shared_ptr < stats : : ConnectionStatistics > connectionStatistics = nullptr ;
2020-01-23 20:57:58 -05:00
bool block_flood = true ;
2019-07-17 13:37:18 -04:00
FloodPoints floodPoints = 0 ;
std : : shared_ptr < ClientChannelView > channels ;
std : : shared_mutex channel_lock ;
std : : mutex cached_permissions_lock ;
2020-01-26 08:21:34 -05:00
std : : vector < std : : pair < permission : : PermissionType , permission : : v2 : : PermissionFlaggedValue > > cached_permissions ; /* contains all needed permissions which are set */
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
permission : : v2 : : PermissionFlaggedValue channels_view_power { 0 , false } ;
permission : : v2 : : PermissionFlaggedValue channels_ignore_view { 0 , false } ;
permission : : v2 : : PermissionFlaggedValue cpmerission_whisper_power { 0 , false } ;
permission : : v2 : : PermissionFlaggedValue cpmerission_needed_whisper_power { 0 , false } ;
2019-07-17 13:37:18 -04:00
bool subscribeToAll = false ;
2020-01-23 20:57:58 -05:00
uint16_t join_state_id = 1 ; /* default channel value is 0 and by default we need to calculate at least once, so we use 1 */
2020-01-26 08:21:34 -05:00
permission : : PermissionType calculate_and_get_join_state ( const std : : shared_ptr < BasicChannel > & ) ;
2019-07-17 13:37:18 -04:00
std : : weak_ptr < MusicClient > selectedBot ;
2020-01-23 20:57:58 -05:00
std : : weak_ptr < MusicClient > subscribed_bot ;
2020-02-02 08:58:46 -05:00
std : : weak_ptr < ts : : music : : Playlist > _subscribed_playlist { } ;
2019-07-17 13:37:18 -04:00
2020-08-13 06:58:19 -04:00
bool loadDataForCurrentServer ( ) override ;
2020-01-23 20:57:58 -05:00
virtual void tick ( const std : : chrono : : system_clock : : time_point & time ) ;
2019-07-17 13:37:18 -04:00
//Locked by everything who has something todo with command handling
threads : : Mutex command_lock ; /* Note: This mutex must be recursive! */
std : : vector < std : : function < void ( ) > > postCommandHandler ;
virtual bool handleCommandFull ( Command & , bool disconnectOnFail = false ) ;
2020-01-25 17:42:37 -05:00
virtual command_result handleCommand ( Command & ) ;
command_result handleCommandServerGetVariables ( Command & ) ;
command_result handleCommandServerEdit ( Command & ) ;
command_result handleCommandGetConnectionInfo ( Command & ) ;
command_result handleCommandSetConnectionInfo ( Command & ) ;
command_result handleCommandServerRequestConnectionInfo ( Command & ) ;
command_result handleCommandConnectionInfoAutoUpdate ( Command & ) ;
command_result handleCommandPermissionList ( Command & ) ;
command_result handleCommandPropertyList ( Command & ) ;
command_result handleCommandServerGroupList ( Command & ) ;
command_result handleCommandClientGetIds ( Command & ) ;
command_result handleCommandClientUpdate ( Command & ) ;
command_result handleCommandClientEdit ( Command & ) ;
command_result handleCommandClientEdit ( Command & , const std : : shared_ptr < ConnectedClient > & /* target */ ) ;
command_result handleCommandClientMove ( Command & ) ;
command_result handleCommandClientGetVariables ( Command & ) ;
command_result handleCommandClientKick ( Command & ) ;
command_result handleCommandClientPoke ( Command & ) ;
command_result handleCommandChannelSubscribe ( Command & ) ;
command_result handleCommandChannelSubscribeAll ( Command & ) ;
command_result handleCommandChannelUnsubscribe ( Command & ) ;
command_result handleCommandChannelUnsubscribeAll ( Command & ) ;
command_result handleCommandChannelCreate ( Command & ) ;
command_result handleCommandChannelDelete ( Command & ) ;
command_result handleCommandChannelEdit ( Command & ) ;
command_result handleCommandChannelGetDescription ( Command & ) ;
command_result handleCommandChannelMove ( Command & ) ;
command_result handleCommandChannelPermList ( Command & ) ;
command_result handleCommandChannelAddPerm ( Command & ) ;
command_result handleCommandChannelDelPerm ( Command & ) ;
2019-07-17 13:37:18 -04:00
//Server group manager management
2020-01-25 17:42:37 -05:00
command_result handleCommandServerGroupAdd ( Command & ) ;
2020-06-28 08:01:14 -04:00
command_result handleCommandServerGroupCopy ( Command & ) ;
2020-01-25 17:42:37 -05:00
command_result handleCommandServerGroupRename ( Command & ) ;
command_result handleCommandServerGroupDel ( Command & ) ;
command_result handleCommandServerGroupClientList ( Command & ) ;
command_result handleCommandServerGroupAddClient ( Command & ) ;
2020-06-28 08:01:14 -04:00
command_result handleCommandServerGroupDelClient ( Command & ) ;
2020-01-25 17:42:37 -05:00
command_result handleCommandServerGroupPermList ( Command & ) ;
command_result handleCommandServerGroupAddPerm ( Command & ) ;
command_result handleCommandServerGroupDelPerm ( Command & ) ;
command_result handleCommandServerGroupAutoAddPerm ( Command & ) ;
command_result handleCommandServerGroupAutoDelPerm ( Command & ) ;
2020-01-26 08:21:34 -05:00
command_result handleCommandClientAddPerm ( Command & ) ;
command_result handleCommandClientDelPerm ( Command & ) ;
command_result handleCommandClientPermList ( Command & ) ;
2020-01-25 17:42:37 -05:00
2020-01-26 08:21:34 -05:00
command_result handleCommandChannelClientAddPerm ( Command & ) ;
command_result handleCommandChannelClientDelPerm ( Command & ) ;
command_result handleCommandChannelClientPermList ( Command & ) ;
2020-01-25 17:42:37 -05:00
command_result handleCommandChannelGroupAdd ( Command & ) ;
command_result handleCommandChannelGroupCopy ( Command & ) ;
command_result handleCommandChannelGroupRename ( Command & ) ;
command_result handleCommandChannelGroupDel ( Command & ) ;
command_result handleCommandChannelGroupList ( Command & ) ;
command_result handleCommandChannelGroupClientList ( Command & ) ;
command_result handleCommandChannelGroupPermList ( Command & ) ;
command_result handleCommandChannelGroupAddPerm ( Command & ) ;
command_result handleCommandChannelGroupDelPerm ( Command & ) ;
command_result handleCommandSetClientChannelGroup ( Command & ) ;
command_result handleCommandSendTextMessage ( Command & ) ;
command_result handleCommandClientChatComposing ( Command & ) ;
command_result handleCommandClientChatClosed ( Command & ) ;
2019-07-17 13:37:18 -04:00
//File transfare commands
2020-01-26 08:21:34 -05:00
command_result handleCommandFTGetFileList ( Command & ) ;
command_result handleCommandFTCreateDir ( Command & ) ;
command_result handleCommandFTDeleteFile ( Command & ) ;
command_result handleCommandFTInitUpload ( Command & ) ;
command_result handleCommandFTInitDownload ( Command & ) ;
2020-05-13 05:32:08 -04:00
command_result handleCommandFTGetFileInfo ( Command & ) ;
command_result handleCommandFTRenameFile ( Command & ) ;
command_result handleCommandFTList ( Command & ) ;
command_result handleCommandFTStop ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandBanList ( Command & ) ;
command_result handleCommandBanAdd ( Command & ) ;
command_result handleCommandBanEdit ( Command & ) ;
command_result handleCommandBanClient ( Command & ) ;
command_result handleCommandBanDel ( Command & ) ;
command_result handleCommandBanDelAll ( Command & ) ;
command_result handleCommandBanTriggerList ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandTokenList ( Command & ) ;
command_result handleCommandTokenAdd ( Command & ) ;
command_result handleCommandTokenUse ( Command & ) ;
command_result handleCommandTokenDelete ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandClientDbList ( Command & ) ;
command_result handleCommandClientDBEdit ( Command & ) ;
command_result handleCommandClientDbInfo ( Command & ) ;
command_result handleCommandClientDBDelete ( Command & ) ;
command_result handleCommandClientDBFind ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandPluginCmd ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandClientMute ( Command & ) ;
command_result handleCommandClientUnmute ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandComplainAdd ( Command & ) ;
command_result handleCommandComplainList ( Command & ) ;
command_result handleCommandComplainDel ( Command & ) ;
command_result handleCommandComplainDelAll ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandClientGetDBIDfromUID ( Command & ) ;
command_result handleCommandClientGetNameFromDBID ( Command & ) ;
command_result handleCommandClientGetNameFromUid ( Command & ) ;
command_result handleCommandClientGetUidFromClid ( Command & ) ;
2019-07-17 13:37:18 -04:00
//Original from query but still reachable for all
2020-01-25 17:42:37 -05:00
command_result handleCommandClientList ( Command & ) ;
command_result handleCommandWhoAmI ( Command & ) ;
command_result handleCommandServerGroupsByClientId ( Command & ) ; //Maybe not query?
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandClientFind ( Command & ) ;
command_result handleCommandClientInfo ( Command & ) ;
command_result handleCommandVersion ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandVerifyChannelPassword ( Command & ) ;
command_result handleCommandVerifyServerPassword ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandMessageList ( Command & ) ;
command_result handleCommandMessageAdd ( Command & ) ;
command_result handleCommandMessageGet ( Command & ) ;
command_result handleCommandMessageUpdateFlag ( Command & ) ;
command_result handleCommandMessageDel ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandPermGet ( Command & ) ;
command_result handleCommandPermIdGetByName ( Command & ) ;
command_result handleCommandPermFind ( Command & ) ;
command_result handleCommandPermOverview ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandChannelFind ( Command & ) ;
command_result handleCommandChannelInfo ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandMusicBotCreate ( Command & ) ;
command_result handleCommandMusicBotDelete ( Command & ) ;
command_result handleCommandMusicBotSetSubscription ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandMusicBotPlayerInfo ( Command & ) ;
command_result handleCommandMusicBotPlayerAction ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandMusicBotQueueList ( Command & ) ;
command_result handleCommandMusicBotQueueAdd ( Command & ) ;
command_result handleCommandMusicBotQueueRemove ( Command & ) ;
command_result handleCommandMusicBotQueueReorder ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandMusicBotPlaylistAssign ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-23 20:57:58 -05:00
/* playlist management */
2020-01-25 17:42:37 -05:00
command_result handleCommandPlaylistList ( Command & ) ;
command_result handleCommandPlaylistCreate ( Command & ) ;
command_result handleCommandPlaylistDelete ( Command & ) ;
2020-02-02 08:58:46 -05:00
command_result handleCommandPlaylistSetSubscription ( Command & ) ;
2020-02-01 08:32:16 -05:00
2020-01-25 17:42:37 -05:00
command_result handleCommandPlaylistPermList ( Command & ) ;
command_result handleCommandPlaylistAddPerm ( Command & ) ;
command_result handleCommandPlaylistDelPerm ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-02-21 14:32:25 -05:00
command_result handleCommandPlaylistClientList ( Command & ) ;
2020-02-01 08:32:16 -05:00
command_result handleCommandPlaylistClientPermList ( Command & ) ;
command_result handleCommandPlaylistClientAddPerm ( Command & ) ;
command_result handleCommandPlaylistClientDelPerm ( Command & ) ;
2020-01-23 20:57:58 -05:00
/* playlist properties */
2020-01-25 17:42:37 -05:00
command_result handleCommandPlaylistInfo ( Command & ) ;
command_result handleCommandPlaylistEdit ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandPlaylistSongList ( Command & ) ;
2020-02-02 08:58:46 -05:00
command_result handleCommandPlaylistSongSetCurrent ( Command & ) ;
2020-01-25 17:42:37 -05:00
command_result handleCommandPlaylistSongAdd ( Command & ) ;
command_result handleCommandPlaylistSongReorder ( Command & ) ;
command_result handleCommandPlaylistSongRemove ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandPermReset ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-26 08:21:34 -05:00
command_result handleCommandHelp ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandUpdateMyTsId ( Command & ) ;
command_result handleCommandUpdateMyTsData ( Command & ) ;
2019-07-17 13:37:18 -04:00
/// <summary>
/// With a whisper list set a client can talk to the specified clients and channels bypassing the standard rule that voice is only transmitted to the current channel. Whisper lists can be defined for individual clients.
/// </summary>
/// <remarks>
/// To control which client is allowed to whisper to own client, the Library implements an internal whisper whitelist mechanism. When a client receives a whisper while the whispering client has not yet been added to the whisper allow list, the receiving client gets the <see cref="Connection.WhisperIgnored"/>-Event. Note that whisper voice data is not received until the sending client is added to the receivers whisper allow list.
/// </remarks>
/// <param name="targetChannelArray">array of channels to whisper to, set to null to disable</param>
/// <param name="targetClientArray">array of clients to whisper to, set to null to disable</param>
//CMD_TODO handleCommandSetWhisperlist
//CMD_TODO handleCommandServerTempPasswordList
//CMD_TODO handleCommandServerTempPasswordDel
//CMD_TODO handleCommandServerTempPasswordAdd -> servertemppasswordadd pw=PWD desc=DES duration=1200 (20 min) tcid=4 tcpw=asdasd (channel password)
//Legacy, for TeamSpeak 3
2020-01-25 17:42:37 -05:00
command_result handleCommandClientSetServerQueryLogin ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandQueryList ( Command & ) ;
command_result handleCommandQueryRename ( Command & ) ;
command_result handleCommandQueryCreate ( Command & ) ;
command_result handleCommandQueryDelete ( Command & ) ;
command_result handleCommandQueryChangePassword ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandConversationHistory ( Command & ) ;
command_result handleCommandConversationFetch ( Command & ) ;
command_result handleCommandConversationMessageDelete ( Command & ) ;
2019-07-19 16:55:03 -04:00
2020-01-25 17:42:37 -05:00
command_result handleCommandLogView ( Command & ) ;
2020-06-28 08:01:14 -04:00
command_result handleCommandLogQuery ( Command & ) ;
command_result handleCommandLogAdd ( Command & ) ;
2019-07-17 13:37:18 -04:00
2020-06-16 06:57:20 -04:00
command_result handleCommandListFeatureSupport ( Command & cmd ) ;
2019-07-17 13:37:18 -04:00
//handleCommandClientSiteReport() -> return findError(0x00)
//handleCommandChannelCreatePrivate() -> return findError(0x02)
//handleCommandCustome_Unknown_Command() -> return findError(0x100)
2020-01-25 17:42:37 -05:00
command_result handleCommandDummy_IpChange ( Command & ) ;
2019-07-17 13:37:18 -04:00
//handleCommandDummy_NewIp
//handleCommandDummy_ConnectFailed
//handleCommandDummy_ConnectionLost
//Not needed - completly useless
//CMD_TODO handleCommandCustomInfo
//CMD_TODO handleCommandCustomSearch
//CMD_TODO serverquerycmd
void sendChannelList ( bool lock_channel_tree ) ;
void sendServerInit ( ) ;
void sendTSPermEditorWarning ( ) ;
void sendChannelDescription ( const std : : shared_ptr < BasicChannel > & , bool lock_tree ) ;
bool handleTextMessage ( ChatMessageMode , std : : string , const std : : shared_ptr < ConnectedClient > & /* sender target */ ) ;
typedef std : : function < void ( const std : : shared_ptr < ConnectedClient > & /* sender */ , const std : : string & /* message */ ) > handle_text_command_fn_t ;
bool handle_text_command (
2020-01-23 20:57:58 -05:00
ChatMessageMode ,
const std : : string & /* key */ ,
const std : : deque < std : : string > & /* arguments */ ,
2019-07-17 13:37:18 -04:00
const handle_text_command_fn_t & /* send function */ ,
const std : : shared_ptr < ConnectedClient > & /* sender target */
) ;
inline std : : string notify_response_command ( const std : : string_view & notify ) {
2020-01-23 20:57:58 -05:00
if ( this - > getExternalType ( ) = = ClientType : : CLIENT_TEAMSPEAK )
return std : : string ( notify ) ;
return " " ;
2019-07-17 13:37:18 -04:00
}
} ;
2020-02-01 08:32:16 -05:00
template < typename T >
struct ConnectedLockedClient {
2020-04-23 09:36:58 -04:00
ConnectedLockedClient ( ) { }
2020-02-01 08:32:16 -05:00
explicit ConnectedLockedClient ( std : : shared_ptr < T > client ) : client { std : : move ( client ) } {
if ( this - > client )
this - > connection_lock = this - > client - > require_connected_state ( ) ;
}
2020-04-23 09:36:58 -04:00
explicit ConnectedLockedClient ( ConnectedLockedClient & & client ) : client { std : : move ( client . client ) } , connection_lock { std : : move ( client . connection_lock ) } { }
2020-02-01 08:32:16 -05:00
2020-04-23 09:36:58 -04:00
inline ConnectedLockedClient & operator = ( const ConnectedLockedClient & other ) {
2020-02-01 08:32:16 -05:00
this - > client = other . client ;
if ( other )
this - > connection_lock = std : : shared_lock { * other . connection_lock . mutex ( ) } ; /* if the other is true (state locked & client) than we could easily acquire a shared lock */
}
2020-04-23 09:36:58 -04:00
inline ConnectedLockedClient & operator = ( ConnectedLockedClient & & other ) {
2020-02-01 08:32:16 -05:00
this - > client = std : : move ( other . client ) ;
this - > connection_lock = std : : move ( other . connection_lock ) ;
}
inline bool valid ( ) const { return ! ! this - > client & & ! ! this - > connection_lock ; }
inline operator bool ( ) const { return this - > valid ( ) ; }
inline bool operator ! ( ) const { return ! this - > valid ( ) ; }
template < typename _T >
inline bool operator = = ( const std : : shared_ptr < _T > & other ) { return this - > client . get ( ) = = other . get ( ) ; }
T * operator - > ( ) { return & * this - > client ; }
T & operator * ( ) { return * this - > client ; }
std : : shared_ptr < T > client ;
std : : shared_lock < std : : shared_mutex > connection_lock { } ;
} ;
2019-07-17 13:37:18 -04:00
}
2020-02-01 08:32:16 -05:00
}
template < typename T1 , typename T2 >
inline bool operator = = ( const std : : shared_ptr < T1 > & a , const ts : : server : : ConnectedLockedClient < T2 > & b ) {
return a . get ( ) = = b . client . get ( ) ;
2019-07-17 13:37:18 -04:00
}