Using new command error system
This commit is contained in:
parent
10092cfab0
commit
bb2e7699dc
@ -578,18 +578,24 @@ bool ConnectedClient::notifyClientNeededPermissions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyError(const CommandResult& result, const std::string& retCode) {
|
||||
bool ConnectedClient::notifyError(const command_result& result, const std::string& retCode) {
|
||||
Command cmd("error");
|
||||
|
||||
cmd["id"] = result.error.errorId;
|
||||
cmd["msg"] = result.error.message;
|
||||
if(result.is_detailed()) {
|
||||
auto detailed = result.details();
|
||||
cmd["id"] = (int) detailed->error_id;
|
||||
cmd["msg"] = findError(detailed->error_id).message;
|
||||
|
||||
for(const auto& extra : detailed->extra_properties)
|
||||
cmd[extra.first] = extra.second;
|
||||
} else {
|
||||
cmd["id"] = (int) result.error_code();
|
||||
cmd["msg"] = findError(result.error_code()).message;
|
||||
}
|
||||
|
||||
if(retCode.length() > 0)
|
||||
cmd["return_code"] = retCode;
|
||||
|
||||
for(const auto& extra : result.extraProperties)
|
||||
cmd[extra.first] = extra.second;
|
||||
|
||||
this->sendCommand(cmd);
|
||||
return true;
|
||||
}
|
||||
@ -792,60 +798,46 @@ bool ConnectedClient::handleCommandFull(Command& cmd, bool disconnectOnFail) {
|
||||
logTrace(this->getServerId() == 0 ? LOG_QUERY : this->getServerId(), "{}[Command][Client -> Server] Processing command: {}", CLIENT_STR_LOG_PREFIX, cmd.build(false));
|
||||
#endif
|
||||
|
||||
CommandResult result;
|
||||
command_result result;
|
||||
try {
|
||||
result = this->handleCommand(cmd);
|
||||
} catch(invalid_argument& ex){
|
||||
debugMessage(this->getServerId(), "{}[Command] Execution throws invalid_argument exception ({}).", CLIENT_STR_LOG_PREFIX, ex.what());
|
||||
logWarning(this->getServerId(), "{}[Command] Failed to handle command. Received invalid argument exception: {}", CLIENT_STR_LOG_PREFIX, ex.what());
|
||||
if(disconnectOnFail) {
|
||||
this->disconnect("Invalid argument (" + string(ex.what()) + ")");
|
||||
return false;
|
||||
} else {
|
||||
result = {findError("parameter_convert"), "Invalid argument (" + string(ex.what()) + ")"};
|
||||
result = command_result{error::parameter_convert};
|
||||
}
|
||||
} catch (exception& ex) {
|
||||
logWarning(this->getServerId(), "{}[Command] Failed to handle command. Received exception with message: {}", CLIENT_STR_LOG_PREFIX, ex.what());
|
||||
if(disconnectOnFail) {
|
||||
this->disconnect("Error while command handling (" + string(ex.what()) + ")!");
|
||||
return false;
|
||||
} else {
|
||||
result = {findError("vs_critical"), "error while command handling (" + string(ex.what()) + ")"};
|
||||
result = command_result{error::vs_critical};
|
||||
}
|
||||
} catch (...) {
|
||||
this->disconnect("Error while command handling! (unknown)");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool generateReturnStatus = false;
|
||||
if(result.type() == PERM_ERROR){
|
||||
if(result.error_code() != error::ok || this->getType() == ClientType::CLIENT_QUERY){
|
||||
generateReturnStatus = true;
|
||||
} else if(cmd["return_code"].size() > 0) {
|
||||
generateReturnStatus = !cmd["return_code"].string().empty();
|
||||
}
|
||||
if(this->getType() == ClientType::CLIENT_QUERY)
|
||||
generateReturnStatus = true;
|
||||
|
||||
if (!result) {
|
||||
generateReturnStatus = true;
|
||||
|
||||
stringstream ss;
|
||||
ss << "{";
|
||||
for(auto it = result.extraProperties.begin(); it != result.extraProperties.end();){
|
||||
ss << it->first << " = " << it->second;
|
||||
if(++it != result.extraProperties.end())
|
||||
ss << ", ";
|
||||
}
|
||||
ss << "}" << endl;
|
||||
logTrace(this->getServerId(), "{}[Command] Command {} with return code {} fails and returns error code {:#06x}. Properties: {}", CLIENT_STR_LOG_PREFIX, cmd.command(), cmd["return_code"].size() ? "\"" + cmd["return_code"].first().as<std::string>() + "\"" : "<undefined>", result.error.errorId, ss.str());
|
||||
}
|
||||
|
||||
if(generateReturnStatus)
|
||||
this->notifyError(result, cmd["return_code"].size() > 0 ? cmd["return_code"].first().as<std::string>() : "");
|
||||
|
||||
if(!result && this->state == ConnectionState::INIT_HIGH) {
|
||||
if(result.error_code() != error::ok && this->state == ConnectionState::INIT_HIGH)
|
||||
this->closeConnection(system_clock::now()); //Disconnect now
|
||||
}
|
||||
|
||||
for (const auto& handler : postCommandHandler)
|
||||
handler();
|
||||
|
||||
postCommandHandler.clear();
|
||||
end = system_clock::now();
|
||||
if(end - start > milliseconds(10)) {
|
||||
@ -854,6 +846,7 @@ bool ConnectedClient::handleCommandFull(Command& cmd, bool disconnectOnFail) {
|
||||
else
|
||||
logWarning(this->getServerId(), "Command handling of command {} needs {}ms.", cmd.command(), duration_cast<milliseconds>(end - start).count());
|
||||
}
|
||||
result.release_details();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7,22 +7,19 @@
|
||||
#include "../channel/ClientChannelView.h"
|
||||
#include "DataClient.h"
|
||||
|
||||
#define CLIENT_LOG_PREFIX_(this) "[" << this->getLoggingPeerIp() << ":" << this->getPeerPort() << "/" << this->getDisplayName() << "]"
|
||||
#define CLIENT_LOG_PREFIX CLIENT_LOG_PREFIX_(this)
|
||||
|
||||
#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 \
|
||||
if(!this->server) return {findError("server_invalid_id"), "invalid bound server"}
|
||||
if(!this->server) return command_result{error::server_invalid_id};
|
||||
|
||||
/* TODO: Play lock the server here with read? So the client dosn't get kicked within that moment */
|
||||
#define CMD_REF_SERVER(variable_name) \
|
||||
std::shared_ptr<TSServer> variable_name = this->getServer(); \
|
||||
if(!variable_name) return {findError("server_invalid_id"), "invalid bound server"}
|
||||
if(!variable_name) return command_result{error::server_invalid_id};
|
||||
|
||||
#define CMD_REQ_CHANNEL \
|
||||
if(!this->currentChannel) return {findError("channel_invalid_id"), "invalid bound channel"}
|
||||
if(!this->currentChannel) return command_result{error::channel_invalid_id};
|
||||
|
||||
#define CMD_RESET_IDLE \
|
||||
do { \
|
||||
@ -30,22 +27,22 @@ do { \
|
||||
} while(false)
|
||||
|
||||
#define CMD_REQ_PARM(parm) \
|
||||
if(!cmd[0].has(parm)) return {findError("parameter_not_found"), parm}
|
||||
if(!cmd[0].has(parm)) return command_result{error::parameter_not_found};
|
||||
|
||||
//the message here is show to the manager!
|
||||
#define CMD_CHK_AND_INC_FLOOD_POINTS(num) \
|
||||
this->increaseFloodPoints(num); \
|
||||
if(this->shouldFloodBlock()) return {findError("ban_flooding"), "You reached the flood limit"};
|
||||
if(this->shouldFloodBlock()) return command_result{error::ban_flooding};
|
||||
|
||||
#define CMD_CHK_PARM_COUNT(count) \
|
||||
if(cmd.bulkCount() != count) return {findError("parameter_invalid_count"), ""};
|
||||
if(cmd.bulkCount() != count) return command_result{error::parameter_invalid_count};
|
||||
|
||||
|
||||
|
||||
#define PERM_CHECK_CHANNEL_CR(pr, required, channel, req, cache) \
|
||||
do { \
|
||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, pr, required, channel, req, cache)) {\
|
||||
return ts::CommandResultPermissionError(pr); \
|
||||
return command_result{pr}; \
|
||||
}\
|
||||
} while(false)
|
||||
|
||||
@ -62,7 +59,7 @@ do { \
|
||||
#define CACHED_PERM_CHECK(permission_type, required, ...) \
|
||||
do { \
|
||||
if(!this->permission_granted(this->cached_permission_value(permission_type), required, #__VA_ARGS__)) \
|
||||
return CommandResultPermissionError{permission_type}; \
|
||||
return command_result{permission_type}; \
|
||||
} while(0)
|
||||
|
||||
//p = permission | target_permission = channel permission | channel = target channel | requires a power
|
||||
@ -148,7 +145,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Notifies general stuff **/
|
||||
virtual bool notifyError(const CommandResult&, const std::string& retCode = "");
|
||||
virtual bool notifyError(const command_result&, const std::string& retCode = "");
|
||||
|
||||
/** Notifies (after request) */
|
||||
bool sendNeededPermissions(bool /* force an update */); /* invoke this because it dosn't spam the client */
|
||||
@ -387,189 +384,189 @@ namespace ts {
|
||||
threads::Mutex command_lock; /* Note: This mutex must be recursive! */
|
||||
std::vector<std::function<void()>> postCommandHandler;
|
||||
virtual bool handleCommandFull(Command&, bool disconnectOnFail = false);
|
||||
virtual CommandResult handleCommand(Command&);
|
||||
virtual command_result handleCommand(Command&);
|
||||
|
||||
CommandResult handleCommandServerGetVariables(Command&);
|
||||
CommandResult handleCommandServerEdit(Command&);
|
||||
command_result handleCommandServerGetVariables(Command&);
|
||||
command_result handleCommandServerEdit(Command&);
|
||||
|
||||
CommandResult handleCommandGetConnectionInfo(Command&);
|
||||
CommandResult handleCommandSetConnectionInfo(Command&);
|
||||
CommandResult handleCommandServerRequestConnectionInfo(Command&);
|
||||
CommandResult handleCommandConnectionInfoAutoUpdate(Command&);
|
||||
CommandResult handleCommandPermissionList(Command&);
|
||||
CommandResult handleCommandPropertyList(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&);
|
||||
|
||||
CommandResult handleCommandServerGroupList(Command&);
|
||||
command_result handleCommandServerGroupList(Command&);
|
||||
|
||||
CommandResult handleCommandClientGetIds(Command&);
|
||||
CommandResult handleCommandClientUpdate(Command&);
|
||||
CommandResult handleCommandClientEdit(Command&);
|
||||
CommandResult handleCommandClientEdit(Command&, const std::shared_ptr<ConnectedClient>& /* target */);
|
||||
CommandResult handleCommandClientMove(Command&);
|
||||
CommandResult handleCommandClientGetVariables(Command&);
|
||||
CommandResult handleCommandClientKick(Command&);
|
||||
CommandResult handleCommandClientPoke(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&);
|
||||
|
||||
CommandResult handleCommandChannelSubscribe(Command&);
|
||||
CommandResult handleCommandChannelSubscribeAll(Command&);
|
||||
CommandResult handleCommandChannelUnsubscribe(Command&);
|
||||
CommandResult handleCommandChannelUnsubscribeAll(Command&);
|
||||
CommandResult handleCommandChannelCreate(Command&);
|
||||
CommandResult handleCommandChannelDelete(Command&);
|
||||
CommandResult handleCommandChannelEdit(Command&);
|
||||
CommandResult handleCommandChannelGetDescription(Command&);
|
||||
CommandResult handleCommandChannelMove(Command&);
|
||||
CommandResult handleCommandChannelPermList(Command&);
|
||||
CommandResult handleCommandChannelAddPerm(Command&);
|
||||
CommandResult handleCommandChannelDelPerm(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&);
|
||||
|
||||
//Server group manager management
|
||||
CommandResult handleCommandServerGroupCopy(Command&);
|
||||
CommandResult handleCommandServerGroupAdd(Command&);
|
||||
CommandResult handleCommandServerGroupRename(Command&);
|
||||
CommandResult handleCommandServerGroupDel(Command&);
|
||||
CommandResult handleCommandServerGroupClientList(Command&);
|
||||
CommandResult handleCommandServerGroupDelClient(Command&);
|
||||
CommandResult handleCommandServerGroupAddClient(Command&);
|
||||
CommandResult handleCommandServerGroupPermList(Command&);
|
||||
CommandResult handleCommandServerGroupAddPerm(Command&);
|
||||
CommandResult handleCommandServerGroupDelPerm(Command&);
|
||||
command_result handleCommandServerGroupCopy(Command&);
|
||||
command_result handleCommandServerGroupAdd(Command&);
|
||||
command_result handleCommandServerGroupRename(Command&);
|
||||
command_result handleCommandServerGroupDel(Command&);
|
||||
command_result handleCommandServerGroupClientList(Command&);
|
||||
command_result handleCommandServerGroupDelClient(Command&);
|
||||
command_result handleCommandServerGroupAddClient(Command&);
|
||||
command_result handleCommandServerGroupPermList(Command&);
|
||||
command_result handleCommandServerGroupAddPerm(Command&);
|
||||
command_result handleCommandServerGroupDelPerm(Command&);
|
||||
|
||||
CommandResult handleCommandServerGroupAutoAddPerm(Command&);
|
||||
CommandResult handleCommandServerGroupAutoDelPerm(Command&);
|
||||
command_result handleCommandServerGroupAutoAddPerm(Command&);
|
||||
command_result handleCommandServerGroupAutoDelPerm(Command&);
|
||||
|
||||
CommandResult handleCommandClientAddPerm(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandClientDelPerm(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandClientPermList(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandClientAddPerm(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandClientDelPerm(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandClientPermList(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandChannelClientAddPerm(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandChannelClientDelPerm(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandChannelClientPermList(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandChannelClientAddPerm(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandChannelClientDelPerm(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandChannelClientPermList(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandChannelGroupAdd(Command&);
|
||||
CommandResult handleCommandChannelGroupCopy(Command&);
|
||||
CommandResult handleCommandChannelGroupRename(Command&);
|
||||
CommandResult handleCommandChannelGroupDel(Command&);
|
||||
CommandResult handleCommandChannelGroupList(Command&);
|
||||
CommandResult handleCommandChannelGroupClientList(Command&);
|
||||
CommandResult handleCommandChannelGroupPermList(Command&);
|
||||
CommandResult handleCommandChannelGroupAddPerm(Command&);
|
||||
CommandResult handleCommandChannelGroupDelPerm(Command&);
|
||||
CommandResult handleCommandSetClientChannelGroup(Command&);
|
||||
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&);
|
||||
|
||||
CommandResult handleCommandSendTextMessage(Command&);
|
||||
CommandResult handleCommandClientChatComposing(Command&);
|
||||
CommandResult handleCommandClientChatClosed(Command&);
|
||||
command_result handleCommandSendTextMessage(Command&);
|
||||
command_result handleCommandClientChatComposing(Command&);
|
||||
command_result handleCommandClientChatClosed(Command&);
|
||||
|
||||
//File transfare commands
|
||||
CommandResult handleCommandFTGetFileList(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandFTCreateDir(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandFTDeleteFile(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandFTInitUpload(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandFTInitDownload(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandFTGetFileInfo(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTGetFileList(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTCreateDir(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTDeleteFile(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTInitUpload(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTInitDownload(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandFTGetFileInfo(Command&); //TODO: Use cached permission values
|
||||
//CMD_TODO handleCommandFTGetFileInfo -> 5 points
|
||||
//CMD_TODO handleCommandFTStop -> 5 points
|
||||
//CMD_TODO handleCommandFTRenameFile -> 5 points
|
||||
//CMD_TODO handleCommandFTList -> 5 points
|
||||
|
||||
CommandResult handleCommandBanList(Command&);
|
||||
CommandResult handleCommandBanAdd(Command&);
|
||||
CommandResult handleCommandBanEdit(Command&);
|
||||
CommandResult handleCommandBanClient(Command&);
|
||||
CommandResult handleCommandBanDel(Command&);
|
||||
CommandResult handleCommandBanDelAll(Command&);
|
||||
CommandResult handleCommandBanTriggerList(Command&);
|
||||
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&);
|
||||
|
||||
CommandResult handleCommandTokenList(Command&);
|
||||
CommandResult handleCommandTokenAdd(Command&);
|
||||
CommandResult handleCommandTokenUse(Command&);
|
||||
CommandResult handleCommandTokenDelete(Command&);
|
||||
command_result handleCommandTokenList(Command&);
|
||||
command_result handleCommandTokenAdd(Command&);
|
||||
command_result handleCommandTokenUse(Command&);
|
||||
command_result handleCommandTokenDelete(Command&);
|
||||
|
||||
CommandResult handleCommandClientDbList(Command&);
|
||||
CommandResult handleCommandClientDBEdit(Command&);
|
||||
CommandResult handleCommandClientDbInfo(Command&);
|
||||
CommandResult handleCommandClientDBDelete(Command&);
|
||||
CommandResult handleCommandClientDBFind(Command&);
|
||||
command_result handleCommandClientDbList(Command&);
|
||||
command_result handleCommandClientDBEdit(Command&);
|
||||
command_result handleCommandClientDbInfo(Command&);
|
||||
command_result handleCommandClientDBDelete(Command&);
|
||||
command_result handleCommandClientDBFind(Command&);
|
||||
|
||||
CommandResult handleCommandPluginCmd(Command&);
|
||||
command_result handleCommandPluginCmd(Command&);
|
||||
|
||||
CommandResult handleCommandClientMute(Command&);
|
||||
CommandResult handleCommandClientUnmute(Command&);
|
||||
command_result handleCommandClientMute(Command&);
|
||||
command_result handleCommandClientUnmute(Command&);
|
||||
|
||||
CommandResult handleCommandComplainAdd(Command&);
|
||||
CommandResult handleCommandComplainList(Command&);
|
||||
CommandResult handleCommandComplainDel(Command&);
|
||||
CommandResult handleCommandComplainDelAll(Command&);
|
||||
command_result handleCommandComplainAdd(Command&);
|
||||
command_result handleCommandComplainList(Command&);
|
||||
command_result handleCommandComplainDel(Command&);
|
||||
command_result handleCommandComplainDelAll(Command&);
|
||||
|
||||
CommandResult handleCommandClientGetDBIDfromUID(Command&);
|
||||
CommandResult handleCommandClientGetNameFromDBID(Command&);
|
||||
CommandResult handleCommandClientGetNameFromUid(Command&);
|
||||
CommandResult handleCommandClientGetUidFromClid(Command&);
|
||||
command_result handleCommandClientGetDBIDfromUID(Command&);
|
||||
command_result handleCommandClientGetNameFromDBID(Command&);
|
||||
command_result handleCommandClientGetNameFromUid(Command&);
|
||||
command_result handleCommandClientGetUidFromClid(Command&);
|
||||
|
||||
//Original from query but still reachable for all
|
||||
CommandResult handleCommandClientList(Command&);
|
||||
CommandResult handleCommandWhoAmI(Command&);
|
||||
CommandResult handleCommandServerGroupsByClientId(Command &); //Maybe not query?
|
||||
command_result handleCommandClientList(Command&);
|
||||
command_result handleCommandWhoAmI(Command&);
|
||||
command_result handleCommandServerGroupsByClientId(Command &); //Maybe not query?
|
||||
|
||||
CommandResult handleCommandClientFind(Command&);
|
||||
CommandResult handleCommandClientInfo(Command&);
|
||||
CommandResult handleCommandVersion(Command&);
|
||||
command_result handleCommandClientFind(Command&);
|
||||
command_result handleCommandClientInfo(Command&);
|
||||
command_result handleCommandVersion(Command&);
|
||||
|
||||
CommandResult handleCommandVerifyChannelPassword(Command&);
|
||||
CommandResult handleCommandVerifyServerPassword(Command&);
|
||||
command_result handleCommandVerifyChannelPassword(Command&);
|
||||
command_result handleCommandVerifyServerPassword(Command&);
|
||||
|
||||
CommandResult handleCommandMessageList(Command&);
|
||||
CommandResult handleCommandMessageAdd(Command&);
|
||||
CommandResult handleCommandMessageGet(Command&);
|
||||
CommandResult handleCommandMessageUpdateFlag(Command&);
|
||||
CommandResult handleCommandMessageDel(Command&);
|
||||
command_result handleCommandMessageList(Command&);
|
||||
command_result handleCommandMessageAdd(Command&);
|
||||
command_result handleCommandMessageGet(Command&);
|
||||
command_result handleCommandMessageUpdateFlag(Command&);
|
||||
command_result handleCommandMessageDel(Command&);
|
||||
|
||||
CommandResult handleCommandPermGet(Command&);
|
||||
CommandResult handleCommandPermIdGetByName(Command&);
|
||||
CommandResult handleCommandPermFind(Command&);
|
||||
CommandResult handleCommandPermOverview(Command&);
|
||||
command_result handleCommandPermGet(Command&);
|
||||
command_result handleCommandPermIdGetByName(Command&);
|
||||
command_result handleCommandPermFind(Command&);
|
||||
command_result handleCommandPermOverview(Command&);
|
||||
|
||||
CommandResult handleCommandChannelFind(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandChannelInfo(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandChannelFind(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandChannelInfo(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandMusicBotCreate(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandMusicBotDelete(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandMusicBotSetSubscription(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotCreate(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotDelete(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotSetSubscription(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandMusicBotPlayerInfo(Command&); //TODO: Use cached permission values
|
||||
CommandResult handleCommandMusicBotPlayerAction(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotPlayerInfo(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotPlayerAction(Command&); //TODO: Use cached permission values
|
||||
|
||||
command_result handleCommandMusicBotQueueList(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotQueueAdd(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotQueueRemove(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandMusicBotQueueReorder(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandMusicBotPlaylistAssign(Command&);
|
||||
command_result handleCommandMusicBotPlaylistAssign(Command&);
|
||||
|
||||
/* playlist management */
|
||||
CommandResult handleCommandPlaylistList(Command&);
|
||||
CommandResult handleCommandPlaylistCreate(Command&);
|
||||
CommandResult handleCommandPlaylistDelete(Command&);
|
||||
CommandResult handleCommandPlaylistPermList(Command&);
|
||||
CommandResult handleCommandPlaylistAddPerm(Command&);
|
||||
CommandResult handleCommandPlaylistDelPerm(Command&);
|
||||
command_result handleCommandPlaylistList(Command&);
|
||||
command_result handleCommandPlaylistCreate(Command&);
|
||||
command_result handleCommandPlaylistDelete(Command&);
|
||||
command_result handleCommandPlaylistPermList(Command&);
|
||||
command_result handleCommandPlaylistAddPerm(Command&);
|
||||
command_result handleCommandPlaylistDelPerm(Command&);
|
||||
|
||||
/* playlist properties */
|
||||
CommandResult handleCommandPlaylistInfo(Command&);
|
||||
CommandResult handleCommandPlaylistEdit(Command&);
|
||||
command_result handleCommandPlaylistInfo(Command&);
|
||||
command_result handleCommandPlaylistEdit(Command&);
|
||||
|
||||
CommandResult handleCommandPlaylistSongList(Command&);
|
||||
CommandResult handleCommandPlaylistSongAdd(Command&);
|
||||
CommandResult handleCommandPlaylistSongReorder(Command&);
|
||||
CommandResult handleCommandPlaylistSongRemove(Command&);
|
||||
command_result handleCommandPlaylistSongList(Command&);
|
||||
command_result handleCommandPlaylistSongAdd(Command&);
|
||||
command_result handleCommandPlaylistSongReorder(Command&);
|
||||
command_result handleCommandPlaylistSongRemove(Command&);
|
||||
|
||||
CommandResult handleCommandPermReset(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandPermReset(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandHelp(Command&); //TODO: Use cached permission values
|
||||
command_result handleCommandHelp(Command&); //TODO: Use cached permission values
|
||||
|
||||
CommandResult handleCommandUpdateMyTsId(Command&);
|
||||
CommandResult handleCommandUpdateMyTsData(Command&);
|
||||
command_result handleCommandUpdateMyTsId(Command&);
|
||||
command_result handleCommandUpdateMyTsData(Command&);
|
||||
/// <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>
|
||||
@ -585,26 +582,26 @@ namespace ts {
|
||||
//CMD_TODO handleCommandServerTempPasswordAdd -> servertemppasswordadd pw=PWD desc=DES duration=1200 (20 min) tcid=4 tcpw=asdasd (channel password)
|
||||
|
||||
//Legacy, for TeamSpeak 3
|
||||
CommandResult handleCommandClientSetServerQueryLogin(Command&);
|
||||
command_result handleCommandClientSetServerQueryLogin(Command&);
|
||||
|
||||
CommandResult handleCommandQueryList(Command&);
|
||||
CommandResult handleCommandQueryRename(Command&);
|
||||
CommandResult handleCommandQueryCreate(Command&);
|
||||
CommandResult handleCommandQueryDelete(Command&);
|
||||
CommandResult handleCommandQueryChangePassword(Command&);
|
||||
command_result handleCommandQueryList(Command&);
|
||||
command_result handleCommandQueryRename(Command&);
|
||||
command_result handleCommandQueryCreate(Command&);
|
||||
command_result handleCommandQueryDelete(Command&);
|
||||
command_result handleCommandQueryChangePassword(Command&);
|
||||
|
||||
CommandResult handleCommandConversationHistory(Command&);
|
||||
CommandResult handleCommandConversationFetch(Command&);
|
||||
CommandResult handleCommandConversationMessageDelete(Command&);
|
||||
command_result handleCommandConversationHistory(Command&);
|
||||
command_result handleCommandConversationFetch(Command&);
|
||||
command_result handleCommandConversationMessageDelete(Command&);
|
||||
|
||||
CommandResult handleCommandLogView(Command&);
|
||||
command_result handleCommandLogView(Command&);
|
||||
//CMD_TODO handleCommandLogAdd
|
||||
|
||||
//handleCommandClientSiteReport() -> return findError(0x00)
|
||||
//handleCommandChannelCreatePrivate() -> return findError(0x02)
|
||||
//handleCommandCustome_Unknown_Command() -> return findError(0x100)
|
||||
|
||||
CommandResult handleCommandDummy_IpChange(Command&);
|
||||
command_result handleCommandDummy_IpChange(Command&);
|
||||
//handleCommandDummy_NewIp
|
||||
//handleCommandDummy_ConnectFailed
|
||||
//handleCommandDummy_ConnectionLost
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -103,13 +103,17 @@ bool ConnectedClient::handleTextMessage(ChatMessageMode mode, std::string text,
|
||||
return true; \
|
||||
}
|
||||
|
||||
//TODO: Correct error message print!
|
||||
#define HANDLE_CMD_ERROR(_message) \
|
||||
send_message(serverInstance->musicRoot(), string(_message) + ": action failed");
|
||||
/*
|
||||
if(result.extraProperties.count("extra_msg") > 0) \
|
||||
send_message(serverInstance->musicRoot(), string(_message) + ": " + result.extraProperties["extra_msg"]); \
|
||||
else if(result.extraProperties.count("failed_permid") > 0) \
|
||||
send_message(serverInstance->musicRoot(), string(_message) + ". (Missing permission " + permission::resolvePermissionData((permission::PermissionType) stoull(result.extraProperties["failed_permid"]))->name + ")"); \
|
||||
else \
|
||||
send_message(serverInstance->musicRoot(), string(_message) + ": " + result.error.message);
|
||||
*/
|
||||
|
||||
#define JOIN_ARGS(variable, index) \
|
||||
string variable; \
|
||||
@ -153,7 +157,8 @@ bool ConnectedClient::handle_text_command(
|
||||
if (TARG(0, "create")) {
|
||||
Command cmd("");
|
||||
auto result = this->handleCommandMusicBotCreate(cmd);
|
||||
if(!result) {
|
||||
if(result.error_code()) {
|
||||
result.release_details();
|
||||
HANDLE_CMD_ERROR("Failed to create music bot");
|
||||
return true;
|
||||
}
|
||||
@ -212,8 +217,9 @@ bool ConnectedClient::handle_text_command(
|
||||
Command cmd("");
|
||||
cmd["client_nickname"] = ss.str();
|
||||
auto result = this->handleCommandClientEdit(cmd, bot);
|
||||
if(!result) {
|
||||
if(result.error_code()) {
|
||||
HANDLE_CMD_ERROR("Failed to rename bot");
|
||||
result.release_details();
|
||||
return true;
|
||||
}
|
||||
send_message(serverInstance->musicRoot(), "Name successfully changed!");
|
||||
@ -499,8 +505,9 @@ bool ConnectedClient::handle_text_command(
|
||||
JOIN_ARGS(value, 3);
|
||||
cmd[arguments[2]] = value;
|
||||
auto result = this->handleCommandClientEdit(cmd, bot);
|
||||
if(!result) {
|
||||
if(result.error_code()) {
|
||||
HANDLE_CMD_ERROR("Failed to change bot property");
|
||||
result.release_details();
|
||||
return true;
|
||||
}
|
||||
send_message(serverInstance->musicRoot(), "Property successfully changed!");
|
||||
|
@ -343,22 +343,24 @@ 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}$");
|
||||
|
||||
CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
TIMING_START(timings);
|
||||
|
||||
{
|
||||
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)
|
||||
return {findError("client_is_flooding"), "To many joins per second per ip"};
|
||||
return command_result{error::client_join_rate_limit_reached};
|
||||
if(config::voice::connectLimit > 0 && this->server->join_attempts["_"] + 1 > config::voice::connectLimit)
|
||||
return {findError("client_is_flooding"), "To many joins per second"};
|
||||
return command_result{error::server_join_rate_limit_reached};
|
||||
this->server->join_attempts[inetAddr]++;
|
||||
this->server->join_attempts["_"]++;
|
||||
}
|
||||
TIMING_STEP(timings, "join atmp c");
|
||||
|
||||
if(!DatabaseHelper::assignDatabaseId(this->server->getSql(), this->server->getServerId(), _this.lock())) return {findError("vs_critical"), "Could not assign database id!"};
|
||||
if(!DatabaseHelper::assignDatabaseId(this->server->getSql(), this->server->getServerId(), _this.lock()))
|
||||
return command_result{error::vs_critical, "Could not assign database id!"};
|
||||
|
||||
TIMING_STEP(timings, "db assign ");
|
||||
this->server->getGroupManager()->enableCache(this->getClientDatabaseId());
|
||||
TIMING_STEP(timings, "gr cache ");
|
||||
@ -423,8 +425,10 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
else if(key == "pubSignCert") continue;
|
||||
else if(key == "client_version" || key == "client_platform") {
|
||||
for(auto& character : cmd[key].string())
|
||||
if(!isascii(character))
|
||||
return {findError("parameter_invalid"), "invalid version or platform"};
|
||||
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};
|
||||
}
|
||||
}
|
||||
|
||||
const auto &info = property::info<property::ClientProperties>(key);
|
||||
@ -433,7 +437,8 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
continue;
|
||||
//return {findError("parameter_invalid"), "Unknown property " + key};
|
||||
}
|
||||
if(!info->validate_input(cmd[key].as<string>())) return {findError("parameter_invalid"), "Unknown value type for " + key};
|
||||
if(!info->validate_input(cmd[key].as<string>()))
|
||||
return command_result{error::parameter_invalid};
|
||||
|
||||
this->properties()[info] = cmd[key].as<std::string>();
|
||||
}
|
||||
@ -459,7 +464,7 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
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)
|
||||
return {findError(0xD01), strvar::transform(ts::config::messages::kick_vpn, strvar::StringValue{"provider.name", provider->name}, strvar::StringValue{"provider.website", provider->side})};
|
||||
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})};
|
||||
}
|
||||
|
||||
if(this->getType() == ClientType::CLIENT_TEAMSPEAK && (permissions[permission::b_client_enforce_valid_hwid] == permNotGranted && permissions[permission::b_client_enforce_valid_hwid] == 0)) {
|
||||
@ -470,14 +475,15 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
!std::regex_match(hwid, regex_hwid_android) &&
|
||||
!std::regex_match(hwid, regex_hwid_ios)
|
||||
) {
|
||||
return {findError("parameter_invalid"), config::messages::kick_invalid_hardware_id};
|
||||
return command_result{error::parameter_invalid, config::messages::kick_invalid_hardware_id};
|
||||
}
|
||||
}
|
||||
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)
|
||||
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true)) return {findError("server_invalid_password"), "invalid server password"};
|
||||
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true))
|
||||
return command_result{error::server_invalid_password};
|
||||
|
||||
size_t clones_uid = 0;
|
||||
size_t clones_ip = 0;
|
||||
@ -496,17 +502,17 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
|
||||
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]);
|
||||
return {findError("client_too_many_clones_connected"), "too many clones connected (uid)"};
|
||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"};
|
||||
}
|
||||
|
||||
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]);
|
||||
return {findError("client_too_many_clones_connected"), "too many clones connected (ip)"};
|
||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"};
|
||||
}
|
||||
|
||||
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]);
|
||||
return {findError("client_too_many_clones_connected"), "too many clones connected (hwid)"};
|
||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
|
||||
}
|
||||
TIMING_STEP(timings, "max clones ");
|
||||
|
||||
@ -560,7 +566,7 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
} else time = "never";
|
||||
fullReason += time + "!";
|
||||
|
||||
return {findError(0xD01), fullReason};
|
||||
return command_result{error::server_connect_banned, fullReason};
|
||||
}
|
||||
TIMING_STEP(timings, "ban resolve");
|
||||
|
||||
@ -577,9 +583,10 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
|
||||
bool allowReserved = permissions[permission::b_client_use_reserved_slot] != permNotGranted && permissions[permission::b_client_use_reserved_slot] != 0;
|
||||
if(reserved > maxClients){
|
||||
if(!allowReserved) return {findError("server_maxclients_reached"), "server max clients reached"};
|
||||
if(!allowReserved)
|
||||
return command_result{error::server_maxclients_reached};
|
||||
} else if(maxClients - (allowReserved ? 0 : reserved) <= count)
|
||||
return {findError("server_maxclients_reached"), "server max clients reached"};
|
||||
return command_result{error::server_maxclients_reached};
|
||||
TIMING_STEP(timings, "max clients");
|
||||
|
||||
|
||||
@ -613,7 +620,7 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) {
|
||||
});
|
||||
|
||||
debugMessage(this->getServerId(), "{} Client init timings: {}", CLIENT_STR_LOG_PREFIX, TIMING_FINISH(timings));
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
/* must be triggered while helding an execute lock */
|
||||
@ -666,7 +673,9 @@ void SpeakingClient::processJoin() {
|
||||
TIMING_STEP(timings, "notify sini");
|
||||
|
||||
if(!ref_server->assignDefaultChannel(this->ref(), false)) {
|
||||
this->notifyError({findError("vs_critical"), "Could not assign default channel!"});
|
||||
auto result = command_result{error::vs_critical, "Could not assign default channel!"};
|
||||
this->notifyError(result);
|
||||
result.release_details();
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
return;
|
||||
}
|
||||
@ -776,19 +785,21 @@ void SpeakingClient::updateChannelClientProperties(bool channel_lock, bool notif
|
||||
this->max_idle_time = this->permissionValueFlagged(permission::i_client_max_idletime, this->currentChannel);
|
||||
}
|
||||
|
||||
CommandResult SpeakingClient::handleCommand(Command &command) {
|
||||
command_result SpeakingClient::handleCommand(Command &command) {
|
||||
if(this->connectionState() == ConnectionState::INIT_HIGH) {
|
||||
if(this->handshake.state == HandshakeState::BEGIN || this->handshake.state == HandshakeState::IDENTITY_PROOF) {
|
||||
CommandResult result;
|
||||
command_result result;
|
||||
if(command.command() == "handshakebegin")
|
||||
result = this->handleCommandHandshakeBegin(command);
|
||||
else if(command.command() == "handshakeindentityproof")
|
||||
result = this->handleCommandHandshakeIdentityProof(command);
|
||||
else
|
||||
result = {findError("client_not_logged_in")};
|
||||
result = command_result{error::client_not_logged_in};
|
||||
|
||||
if(!result)
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
if(result.error_code())
|
||||
this->postCommandHandler.push_back([&]{
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace ts {
|
||||
void updateChannelClientProperties(bool channel_lock, bool notify) override;
|
||||
|
||||
protected:
|
||||
CommandResult handleCommand(Command &command) override;
|
||||
command_result handleCommand(Command &command) override;
|
||||
|
||||
public:
|
||||
void handlePacketVoice(const pipes::buffer_view&, bool head, bool fragmented);
|
||||
@ -68,9 +68,9 @@ namespace ts {
|
||||
void processJoin();
|
||||
void processLeave();
|
||||
|
||||
virtual CommandResult handleCommandHandshakeBegin(Command&);
|
||||
virtual CommandResult handleCommandHandshakeIdentityProof(Command &);
|
||||
virtual CommandResult handleCommandClientInit(Command&);
|
||||
virtual command_result handleCommandHandshakeBegin(Command&);
|
||||
virtual command_result handleCommandHandshakeIdentityProof(Command &);
|
||||
virtual command_result handleCommandClientInit(Command&);
|
||||
|
||||
void triggerVoiceEnd();
|
||||
inline void updateSpeak(bool onlyUpdate, const std::chrono::system_clock::time_point &time);
|
||||
|
@ -23,13 +23,13 @@ void free_ecc(ecc_key* key) {
|
||||
delete key;
|
||||
}
|
||||
|
||||
CommandResult SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !result than the connection will be closed!
|
||||
command_result SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !result than the connection will be closed!
|
||||
if(this->handshake.state != HandshakeState::BEGIN)
|
||||
return {findError("web_handshake_invalid"), "invalid connection state!"};
|
||||
return command_result{error::web_handshake_invalid};
|
||||
|
||||
auto intention = cmd["intention"].as<int>();
|
||||
if(intention != 0)
|
||||
return {findError("web_handshake_unsupported"), ""};
|
||||
return command_result{error::web_handshake_unsupported};
|
||||
|
||||
auto authenticationMethod = cmd["authentication_method"].as<int>();
|
||||
if(authenticationMethod == IdentityType::TEAMSPEAK) {
|
||||
@ -41,7 +41,8 @@ CommandResult SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !
|
||||
this->handshake.identityKey = shared_ptr<ecc_key>(new ecc_key{}, free_ecc);
|
||||
if(ecc_import((u_char*) identity.data(), identity.length(), this->handshake.identityKey.get()) != CRYPT_OK) {
|
||||
this->handshake.identityKey = nullptr;
|
||||
return {findError("web_handshake_invalid"), "invalid ecc key state!"};
|
||||
logWarning(this->getServerId(), "{} Failed to import remote public key.", CLIENT_STR_LOG_PREFIX);
|
||||
return command_result{error::web_handshake_invalid};
|
||||
}
|
||||
|
||||
auto message = "TeaSpeak, made with love and coffee by WolverinDEV (#" + base64::encode(rnd_string(32)) + ")";
|
||||
@ -65,26 +66,26 @@ CommandResult SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !
|
||||
auto& json_str = this->handshake.proof_message;
|
||||
if(!reader->parse(json_str.data(), json_str.data() + json_str.size(), &*this->handshake.identityData, &error)) {
|
||||
debugMessage(this->getServerId(), "[{}] Failed to parse forum account data: {}", error);
|
||||
return {findError("web_handshake_invalid"), "invalid json!"};
|
||||
return command_result{error::web_handshake_invalid};
|
||||
}
|
||||
|
||||
auto& json_data = *this->handshake.identityData;
|
||||
if(json_data["user_id"].isNull())
|
||||
return {findError("web_handshake_invalid"), "Missing json data (user_id)!"};
|
||||
return command_result{error::web_handshake_invalid}; //{findError("web_handshake_invalid"), "Missing json data (user_id)!"};
|
||||
if(json_data["user_name"].isNull())
|
||||
return {findError("web_handshake_invalid"), "Missing json data (user_name)!"};
|
||||
return command_result{error::web_handshake_invalid}; //{findError("web_handshake_invalid"), "Missing json data (user_name)!"};
|
||||
if(json_data["user_group"].isNull())
|
||||
return {findError("web_handshake_invalid"), "Missing json data (user_group)!"};
|
||||
return command_result{error::web_handshake_invalid}; //{findError("web_handshake_invalid"), "Missing json data (user_group)!"};
|
||||
if(json_data["user_groups"].isNull())
|
||||
return {findError("web_handshake_invalid"), "Missing json data (user_groups)!"};
|
||||
return command_result{error::web_handshake_invalid}; //{findError("web_handshake_invalid"), "Missing json data (user_groups)!"};
|
||||
if(json_data["data_age"].isNull())
|
||||
return {findError("web_handshake_invalid"), "Missing json data (data_age)!"};
|
||||
return command_result{error::web_handshake_invalid}; //{findError("web_handshake_invalid"), "Missing json data (data_age)!"};
|
||||
|
||||
//Type test
|
||||
json_data["user_id"].asInt64();
|
||||
|
||||
if(json_data["data_age"].asUInt64() < duration_cast<milliseconds>((system_clock::now() - hours(72)).time_since_epoch()).count())
|
||||
return {findError("web_handshake_invalid"), "Provided data is too old!"};
|
||||
return command_result{error::web_handshake_identity_outdated}; // {findError("web_handshake_invalid"), "Provided data is too old!"};
|
||||
|
||||
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = base64::encode(digest::sha1("TeaSpeak-Forum#" + json_data["user_id"].asString()));
|
||||
|
||||
@ -107,34 +108,37 @@ CommandResult SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !
|
||||
this->properties()[property::CLIENT_TEAFORO_FLAGS] = flags;
|
||||
}
|
||||
} catch (Json::Exception& exception) {
|
||||
return {findError("web_handshake_invalid"), "invalid json!"};
|
||||
debugMessage(this->getServerId(), "{} Failed to parse supplied json: {}", CLIENT_STR_LOG_PREFIX, exception.what());
|
||||
return command_result{error::web_handshake_invalid};
|
||||
}
|
||||
this->sendCommand(Command("handshakeidentityproof"));
|
||||
this->handshake.state = HandshakeState::IDENTITY_PROOF;
|
||||
} else if(authenticationMethod == IdentityType::NICKNAME) {
|
||||
if(!config::server::authentication::name)
|
||||
return {findError("web_handshake_identity_unsupported"), "Name authentication has been disabled"};
|
||||
return command_result{error::web_handshake_unsupported};
|
||||
|
||||
this->handshake.state = HandshakeState::SUCCEEDED;
|
||||
this->handshake.identityType = IdentityType::NICKNAME;
|
||||
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = base64::encode(digest::sha1("UserName#" + cmd["client_nickname"].string()));
|
||||
} else {
|
||||
return {findError("web_handshake_identity_unsupported"), ""};
|
||||
return command_result{error::web_handshake_unsupported};
|
||||
}
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult SpeakingClient::handleCommandHandshakeIdentityProof(Command& cmd) {
|
||||
command_result SpeakingClient::handleCommandHandshakeIdentityProof(Command& cmd) {
|
||||
if(this->handshake.state != HandshakeState::IDENTITY_PROOF)
|
||||
return {findError("web_handshake_invalid"), "invalid connection state!"};
|
||||
return command_result{error::web_handshake_invalid};
|
||||
|
||||
if(this->handshake.identityType == IdentityType::TEASPEAK_FORUM) {
|
||||
auto encodedProof = cmd["proof"].string();
|
||||
auto proof = base64::decode(encodedProof);
|
||||
|
||||
auto key = serverInstance->sslManager()->getRsaKey("teaforo_sign");
|
||||
if(!key) return {findError("web_handshake_identity_unsupported"), "Missing server public key!"};
|
||||
if(!serverInstance->sslManager()->verifySign(key, this->handshake.proof_message, proof)) return {findError("web_handshake_identity_proof_failed"), ""};
|
||||
if(!key)
|
||||
return command_result{error::web_handshake_identity_unsupported};
|
||||
if(!serverInstance->sslManager()->verifySign(key, this->handshake.proof_message, proof))
|
||||
return command_result{error::web_handshake_identity_proof_failed};
|
||||
|
||||
this->properties()[property::CLIENT_TEAFORO_ID] = (int64_t) (*this->handshake.identityData)["user_id"].asInt64();
|
||||
this->properties()[property::CLIENT_TEAFORO_NAME] = (*this->handshake.identityData)["user_name"].asString();
|
||||
@ -143,11 +147,13 @@ CommandResult SpeakingClient::handleCommandHandshakeIdentityProof(Command& cmd)
|
||||
auto proof = base64::decode(cmd["proof"]);
|
||||
|
||||
int result;
|
||||
if(ecc_verify_hash((u_char*) proof.data(), proof.length(), (u_char*) this->handshake.proof_message.data(), this->handshake.proof_message.length(), &result, this->handshake.identityKey.get()) != CRYPT_OK) return {findError("web_handshake_identity_proof_failed"), ""};
|
||||
if(!result) return {findError("web_handshake_identity_proof_failed"), ""};
|
||||
if(ecc_verify_hash((u_char*) proof.data(), proof.length(), (u_char*) this->handshake.proof_message.data(), this->handshake.proof_message.length(), &result, this->handshake.identityKey.get()) != CRYPT_OK)
|
||||
return command_result{error::web_handshake_identity_proof_failed};
|
||||
if(!result)
|
||||
return command_result{error::web_handshake_identity_proof_failed};
|
||||
this->handshake.state = HandshakeState::SUCCEEDED;
|
||||
} else
|
||||
return {findError("web_handshake_invalid"), "identity isn't required to proof authentication"};
|
||||
return command_result{error::web_handshake_invalid};
|
||||
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
#include <misc/memtracker.h>
|
||||
#include "src/InstanceHandler.h"
|
||||
#include <pipes/errors.h>
|
||||
#include <query/command2.h>
|
||||
#include <misc/std_unique_ptr.h>
|
||||
|
||||
using namespace std;
|
||||
@ -76,7 +75,9 @@ void QueryClient::postInitialize() {
|
||||
this->properties()[property::CLIENT_LASTCONNECTED] = duration_cast<seconds>(this->connectTimestamp.time_since_epoch()).count();
|
||||
|
||||
if(ts::config::query::sslMode == 1 && this->connectionType != ConnectionType::SSL_ENCRIPTED) {
|
||||
this->notifyError({findError("failed_connection_initialisation"), "Please use a SSL encryption!"});
|
||||
command_result error{error::failed_connection_initialisation, "Please use a SSL encryption!"};
|
||||
this->notifyError(error);
|
||||
error.release_details();
|
||||
this->disconnect("Please us a SSL encryption for more security.\nThe server denies also all other connections!");
|
||||
return;
|
||||
}
|
||||
@ -495,28 +496,31 @@ bool QueryClient::handleMessage(const pipes::buffer_view& message) {
|
||||
}
|
||||
|
||||
unique_ptr<Command> cmd;
|
||||
command_result error{};
|
||||
try {
|
||||
cmd = make_unique<Command>(Command::parse(pipes::buffer_view{(void*) command.data(), command.length()}, true, !ts::config::server::strict_ut8_mode));
|
||||
} catch(std::invalid_argument& ex) {
|
||||
logTrace(LOG_QUERY, "[{}:{}] Failed to parse command (invalid argument): {}", this->getLoggingPeerIp(), this->getPeerPort(), command);
|
||||
this->notifyError(CommandResult{findError("parameter_convert"), ex.what()});
|
||||
return false;
|
||||
} catch(command_malformed_exception& ex) {
|
||||
logTrace(LOG_QUERY, "[{}:{}] Failed to parse command (malformed command at {}): {}", this->getLoggingPeerIp(), this->getPeerPort(), ex.index(), command);
|
||||
this->notifyError(CommandResult{findError("parameter_convert"), "invalid character @" + to_string(ex.index())});
|
||||
return false;
|
||||
error = command_result{error::parameter_convert};
|
||||
goto handle_error;
|
||||
} catch(std::exception& ex) {
|
||||
logTrace(LOG_QUERY, "[{}:{}] Failed to parse command (exception: {}): {}", this->getLoggingPeerIp(), this->getPeerPort(), ex.what(), command);
|
||||
this->notifyError(CommandResult{ErrorType::VSError, ex.what()});
|
||||
return false;
|
||||
error = command_result{error::vs_critical, std::string{ex.what()}};
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
try {
|
||||
this->handleCommandFull(*cmd);
|
||||
} catch(std::exception& ex) {
|
||||
this->notifyError(CommandResult{ErrorType::VSError, ex.what()});
|
||||
error = command_result{error::vs_critical, std::string{ex.what()}};
|
||||
goto handle_error;
|
||||
}
|
||||
return true;
|
||||
|
||||
handle_error:
|
||||
this->notifyError(error);
|
||||
error.release_details();
|
||||
return false;
|
||||
}
|
||||
|
||||
void QueryClient::sendCommand(const ts::Command &command, bool) {
|
||||
|
@ -86,7 +86,7 @@ namespace ts {
|
||||
|
||||
std::shared_ptr<QueryAccount> query_account;
|
||||
protected:
|
||||
CommandResult handleCommand(Command &command) override;
|
||||
command_result handleCommand(Command &command) override;
|
||||
|
||||
public:
|
||||
//Silent events
|
||||
@ -144,41 +144,41 @@ namespace ts {
|
||||
bool notifyClientLeftViewBanned(const std::shared_ptr<ConnectedClient> &client, const std::string &message, std::shared_ptr<ConnectedClient> invoker, size_t length, bool lock_channel_tree) override;
|
||||
|
||||
private:
|
||||
CommandResult handleCommandExit(Command&);
|
||||
CommandResult handleCommandLogin(Command&);
|
||||
CommandResult handleCommandLogout(Command&);
|
||||
CommandResult handleCommandServerSelect(Command &);
|
||||
CommandResult handleCommandServerInfo(Command&);
|
||||
CommandResult handleCommandChannelList(Command&);
|
||||
CommandResult handleCommandJoin(Command&);
|
||||
CommandResult handleCommandLeft(Command&);
|
||||
command_result handleCommandExit(Command&);
|
||||
command_result handleCommandLogin(Command&);
|
||||
command_result handleCommandLogout(Command&);
|
||||
command_result handleCommandServerSelect(Command &);
|
||||
command_result handleCommandServerInfo(Command&);
|
||||
command_result handleCommandChannelList(Command&);
|
||||
command_result handleCommandJoin(Command&);
|
||||
command_result handleCommandLeft(Command&);
|
||||
|
||||
CommandResult handleCommandServerList(Command&);
|
||||
CommandResult handleCommandServerCreate(Command&);
|
||||
CommandResult handleCommandServerDelete(Command&);
|
||||
CommandResult handleCommandServerStart(Command&);
|
||||
CommandResult handleCommandServerStop(Command&);
|
||||
command_result handleCommandServerList(Command&);
|
||||
command_result handleCommandServerCreate(Command&);
|
||||
command_result handleCommandServerDelete(Command&);
|
||||
command_result handleCommandServerStart(Command&);
|
||||
command_result handleCommandServerStop(Command&);
|
||||
|
||||
CommandResult handleCommandInstanceInfo(Command&);
|
||||
CommandResult handleCommandInstanceEdit(Command&);
|
||||
command_result handleCommandInstanceInfo(Command&);
|
||||
command_result handleCommandInstanceEdit(Command&);
|
||||
|
||||
CommandResult handleCommandBindingList(Command&);
|
||||
command_result handleCommandBindingList(Command&);
|
||||
|
||||
CommandResult handleCommandHostInfo(Command&);
|
||||
command_result handleCommandHostInfo(Command&);
|
||||
|
||||
CommandResult handleCommandGlobalMessage(Command&);
|
||||
command_result handleCommandGlobalMessage(Command&);
|
||||
|
||||
CommandResult handleCommandServerIdGetByPort(Command&);
|
||||
command_result handleCommandServerIdGetByPort(Command&);
|
||||
|
||||
CommandResult handleCommandServerSnapshotDeploy(Command&);
|
||||
CommandResult handleCommandServerSnapshotCreate(Command&);
|
||||
CommandResult handleCommandServerProcessStop(Command&);
|
||||
command_result handleCommandServerSnapshotDeploy(Command&);
|
||||
command_result handleCommandServerSnapshotCreate(Command&);
|
||||
command_result handleCommandServerProcessStop(Command&);
|
||||
|
||||
CommandResult handleCommandServerNotifyRegister(Command&);
|
||||
CommandResult handleCommandServerNotifyList(Command&);
|
||||
CommandResult handleCommandServerNotifyUnregister(Command&);
|
||||
command_result handleCommandServerNotifyRegister(Command&);
|
||||
command_result handleCommandServerNotifyList(Command&);
|
||||
command_result handleCommandServerNotifyUnregister(Command&);
|
||||
|
||||
CommandResult handleCommandSetCompressionMode(Command&);
|
||||
command_result handleCommandSetCompressionMode(Command&);
|
||||
};
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ constexpr unsigned int string_hash(const char* str, int h = 0) {
|
||||
return !str[h] ? 5381 : (string_hash(str, h + 1U) * 33U) ^ str[h];
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommand(Command& cmd) {
|
||||
command_result QueryClient::handleCommand(Command& cmd) {
|
||||
/*
|
||||
if (cmd.command() == "exit" || cmd.command() == "quit") return this->handleCommandExit(cmd);
|
||||
else if (cmd.command() == "use" || cmd.command() == "serverselect") return this->handleCommandServerSelect(cmd);
|
||||
@ -117,14 +117,14 @@ CommandResult QueryClient::handleCommand(Command& cmd) {
|
||||
return ConnectedClient::handleCommand(cmd);
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandExit(Command &) {
|
||||
command_result QueryClient::handleCommandExit(Command &) {
|
||||
logMessage(LOG_QUERY, "[Query] {}:{} disconnected. (Requested by client)", this->getLoggingPeerIp(), this->getPeerPort());
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
//login client_login_name=andreas client_login_password=meinPW
|
||||
CommandResult QueryClient::handleCommandLogin(Command& cmd) {
|
||||
command_result QueryClient::handleCommandLogin(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
|
||||
std::string username, password;
|
||||
@ -144,7 +144,7 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) {
|
||||
threads::MutexLock lock(this->handle->loginLock);
|
||||
|
||||
if(!account)
|
||||
return {findError("client_invalid_password"), "username or password dose not match"};
|
||||
return command_result{error::client_invalid_password, "username or password dose not match"};
|
||||
|
||||
if (account->password != password) {
|
||||
if(!this->whitelisted) {
|
||||
@ -154,15 +154,20 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) {
|
||||
this->postCommandHandler.emplace_back([&](){
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
});
|
||||
return {findError("ban_flooding"), ""};
|
||||
return command_result{error::ban_flooding};
|
||||
}
|
||||
}
|
||||
return {findError("client_invalid_password"), "username or password dose not match"};
|
||||
return command_result{error::client_invalid_password, "username or password dose not match"};
|
||||
}
|
||||
}
|
||||
if(!this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) {
|
||||
Command log("logout");
|
||||
if(!this->handleCommandLogout(log)) return {ErrorType::VSError, "Failed to logout!"};
|
||||
auto result = this->handleCommandLogout(log);
|
||||
if(result.error_code()) {
|
||||
result.release_details();
|
||||
logError(this->getServerId(), "Query client failed to login from old login.");
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
}
|
||||
|
||||
this->query_account = account;
|
||||
@ -190,7 +195,7 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) {
|
||||
if(target_server != this->server)
|
||||
joined_channel = nullptr;
|
||||
if(!target_server)
|
||||
return {findError("server_invalid_id"), "server does not exists anymore"};
|
||||
return command_result{error::server_invalid_id, "server does not exists anymore"};
|
||||
}
|
||||
this->server = target_server;
|
||||
|
||||
@ -226,12 +231,12 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) {
|
||||
this->properties()[property::CLIENT_TOTALCONNECTIONS]++;
|
||||
this->updateChannelClientProperties(true, true);
|
||||
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandLogout(Command &) {
|
||||
command_result QueryClient::handleCommandLogout(Command &) {
|
||||
CMD_RESET_IDLE;
|
||||
if(this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) return {findError("client_not_logged_in"), "not logged in"};
|
||||
if(this->properties()[property::CLIENT_LOGIN_NAME].as<string>().empty()) return command_result{error::client_not_logged_in, "not logged in"};
|
||||
this->properties()[property::CLIENT_LOGIN_NAME] = "";
|
||||
this->query_account = nullptr;
|
||||
|
||||
@ -278,10 +283,10 @@ CommandResult QueryClient::handleCommandLogout(Command &) {
|
||||
|
||||
this->updateChannelClientProperties(true, true);
|
||||
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerSelect(Command &cmd) {
|
||||
command_result QueryClient::handleCommandServerSelect(Command &cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
shared_ptr<TSServer> target;
|
||||
|
||||
@ -295,18 +300,18 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) {
|
||||
if(parm.find_first_not_of("0123456789") == string::npos)
|
||||
target = serverInstance->getVoiceServerManager()->findServerById(static_cast<ServerId>(stol(parm)));
|
||||
|
||||
if(!target && (!cmd[0].has("0") && (!cmd[0].has("sid") || !cmd["sid"] == 0))) return {findError("server_invalid_id"), "Invalid server id"};
|
||||
if(!target && (!cmd[0].has("0") && (!cmd[0].has("sid") || !cmd["sid"] == 0))) return command_result{error::server_invalid_id, "Invalid server id"};
|
||||
|
||||
|
||||
if(target == this->server) return CommandResult::Success;
|
||||
if(target == this->server) return command_result{error::ok};
|
||||
|
||||
if(target) {
|
||||
if(this->query_account && this->query_account->bound_server > 0) {
|
||||
if(target->getServerId() != this->query_account->bound_server)
|
||||
return {findError("server_invalid_id"), "You're a server bound query, and the target server isn't your origin."};
|
||||
return command_result{error::server_invalid_id, "You're a server bound query, and the target server isn't your origin."};
|
||||
} else {
|
||||
auto allowed = target->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_select, this->getType(), nullptr);
|
||||
if(allowed != -1 && allowed <= 0) return CommandResultPermissionError{permission::b_virtualserver_select};
|
||||
if(allowed != -1 && allowed <= 0) return command_result{permission::b_virtualserver_select};
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,23 +367,23 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) {
|
||||
}
|
||||
this->updateChannelClientProperties(true, true);
|
||||
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandJoin(Command &) {
|
||||
command_result QueryClient::handleCommandJoin(Command &) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_RESET_IDLE;
|
||||
if(!this->server->running())
|
||||
return {findError("server_is_not_running"), "server isnt started yet"};
|
||||
return command_result{error::server_is_not_running, "server isnt started yet"};
|
||||
|
||||
if(this->currentChannel)
|
||||
return {findError("server_already_joined"), "already joined!"};
|
||||
return command_result{error::server_already_joined, "already joined!"};
|
||||
|
||||
this->server->assignDefaultChannel(this->ref(), true);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandLeft(Command&) {
|
||||
command_result QueryClient::handleCommandLeft(Command&) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_REQ_CHANNEL;
|
||||
CMD_RESET_IDLE;
|
||||
@ -386,10 +391,10 @@ CommandResult QueryClient::handleCommandLeft(Command&) {
|
||||
PERM_CHECK_CHANNELR(permission::b_virtualserver_select_godmode, 1, nullptr, 1);
|
||||
unique_lock server_channel_lock(this->server->channel_tree_lock);
|
||||
this->server->client_move(this->ref(), nullptr, nullptr, "leaving", ViewReasonId::VREASON_SERVER_LEFT, true, server_channel_lock);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerInfo(Command &) {
|
||||
command_result QueryClient::handleCommandServerInfo(Command &) {
|
||||
CMD_RESET_IDLE;
|
||||
PERM_CHECKR(permission::b_virtualserver_info_view, 1, true);
|
||||
|
||||
@ -469,10 +474,10 @@ CommandResult QueryClient::handleCommandServerInfo(Command &) {
|
||||
}
|
||||
|
||||
this->sendCommand(cmd);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandChannelList(Command& cmd) {
|
||||
command_result QueryClient::handleCommandChannelList(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_virtualserver_channel_list, 1, true);
|
||||
CMD_RESET_IDLE;
|
||||
|
||||
@ -530,10 +535,10 @@ CommandResult QueryClient::handleCommandChannelList(Command& cmd) {
|
||||
}
|
||||
|
||||
this->sendCommand(result);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerList(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerList(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
PERM_CHECKR(permission::b_serverinstance_virtualserver_list, 1, true);
|
||||
Command res("");
|
||||
@ -563,15 +568,15 @@ CommandResult QueryClient::handleCommandServerList(Command& cmd) {
|
||||
}
|
||||
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
PERM_CHECKR(permission::b_virtualserver_create, 1, true);
|
||||
|
||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) {
|
||||
return {findError("vs_critical"), "Server manager isn't started yet or not finished starting"};
|
||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||
}
|
||||
|
||||
string startError;
|
||||
@ -583,9 +588,9 @@ CommandResult QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
threads::MutexLock lock(serverInstance->getVoiceServerManager()->server_create_lock);
|
||||
auto instances = serverInstance->getVoiceServerManager()->serverInstances();
|
||||
if(config::server::max_virtual_server != -1 && instances.size() > config::server::max_virtual_server)
|
||||
return {findError("server_max_vs_reached"), "You reached the via config.yml enabled virtual server limit."};
|
||||
return command_result{error::server_max_vs_reached, "You reached the via config.yml enabled virtual server limit."};
|
||||
if(instances.size() >= 65535)
|
||||
return {findError("server_max_vs_reached"), "You cant create anymore virtual servers. (Software limit reached)"};
|
||||
return command_result{error::server_max_vs_reached, "You cant create anymore virtual servers. (Software limit reached)"};
|
||||
{
|
||||
auto end = system_clock::now();
|
||||
time_wait = duration_cast<milliseconds>(end - start);
|
||||
@ -601,7 +606,7 @@ CommandResult QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
auto _end = system_clock::now();
|
||||
time_create = duration_cast<milliseconds>(_end - _start);
|
||||
}
|
||||
if(!server) return {findError("vs_critical"), "could not create new server"};
|
||||
if(!server) return command_result{error::vs_critical, "could not create new server"};
|
||||
|
||||
for(const auto& key : cmd[0].keys()){
|
||||
if(key == "virtualserver_port") continue;
|
||||
@ -640,64 +645,64 @@ CommandResult QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||
res["time_global"] = time_global.count();
|
||||
res["time_wait"] = time_wait.count();
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerDelete(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
PERM_CHECKR(permission::b_virtualserver_delete, 1, true);
|
||||
|
||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||
return {findError("vs_critical"), "Server manager isn't started yet or not finished starting"};
|
||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||
|
||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||
if(!server) return {findError("server_invalid_id"), "invalid bounded server"};
|
||||
if(!serverInstance->getVoiceServerManager()->deleteServer(server)) return {ErrorType::VSError};
|
||||
return CommandResult::Success;
|
||||
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
||||
if(!serverInstance->getVoiceServerManager()->deleteServer(server)) return command_result{error::vs_critical};
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerStart(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
|
||||
PERM_CHECKR(permission::b_virtualserver_start_any, 1, true);
|
||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||
return {findError("vs_critical"), "Server manager isn't started yet or not finished starting"};
|
||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||
|
||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||
if(!server) return {findError("server_invalid_id"), "invalid bounded server"};
|
||||
if(server->running()) return {findError("server_running"), "server already running"};
|
||||
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
||||
if(server->running()) return command_result{error::server_running, "server already running"};
|
||||
|
||||
if(server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_start, ClientType::CLIENT_QUERY, nullptr) != 1) {
|
||||
if(!this->permissionGranted(permission::PERMTEST_HIGHEST, permission::b_virtualserver_start_any, 1))
|
||||
return CommandResultPermissionError{permission::b_virtualserver_start};
|
||||
return command_result{permission::b_virtualserver_start};
|
||||
}
|
||||
|
||||
string err;
|
||||
if(!server->start(err)) return {findError("vs_critical"), err};
|
||||
return CommandResult::Success;
|
||||
if(!server->start(err)) return command_result{error::vs_critical, err};
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerStop(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
PERM_CHECKR(permission::b_virtualserver_stop, 1, true);
|
||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||
return {findError("vs_critical"), "Server manager isn't started yet or not finished starting"};
|
||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||
|
||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||
if(!server) return {findError("server_invalid_id"), "invalid bounded server"};
|
||||
if(!server->running()) return {findError("server_is_not_running"), "server is not running"};
|
||||
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
||||
if(!server->running()) return command_result{error::server_is_not_running, "server is not running"};
|
||||
|
||||
if(server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_stop, ClientType::CLIENT_QUERY, nullptr) != 1) {
|
||||
if(!this->permissionGranted(permission::PERMTEST_HIGHEST, permission::b_virtualserver_stop_any, 1))
|
||||
return CommandResultPermissionError{permission::b_virtualserver_stop};
|
||||
return command_result{permission::b_virtualserver_stop};
|
||||
}
|
||||
|
||||
server->stop("server stopped");
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
|
||||
CommandResult QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
||||
command_result QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_serverinstance_info_view, 1, true);
|
||||
|
||||
Command res("");
|
||||
@ -707,10 +712,10 @@ CommandResult QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
||||
res["serverinstance_teaspeak"] = true;
|
||||
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
||||
command_result QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_serverinstance_modify_settings, 1, true);
|
||||
|
||||
for(const auto &key : cmd[0].keys()){
|
||||
@ -730,10 +735,10 @@ CommandResult QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
||||
}
|
||||
serverInstance->properties()[info] = cmd[key].string();
|
||||
}
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandHostInfo(Command &) {
|
||||
command_result QueryClient::handleCommandHostInfo(Command &) {
|
||||
PERM_CHECKR(permission::b_serverinstance_info_view, 1, true);
|
||||
|
||||
Command res("");
|
||||
@ -765,37 +770,37 @@ CommandResult QueryClient::handleCommandHostInfo(Command &) {
|
||||
res["connection_filetransfer_bytes_received_total"] = (*stats)[property::CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL].as<string>();
|
||||
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandGlobalMessage(Command& cmd) {
|
||||
command_result QueryClient::handleCommandGlobalMessage(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_serverinstance_textmessage_send, 1, true);
|
||||
|
||||
for(const auto &server : serverInstance->getVoiceServerManager()->serverInstances())
|
||||
if(server->running()) server->broadcastMessage(server->getServerRoot(), cmd["msg"]);
|
||||
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerIdGetByPort(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerIdGetByPort(Command& cmd) {
|
||||
uint16_t port = cmd["virtualserver_port"];
|
||||
auto server = serverInstance->getVoiceServerManager()->findServerByPort(port);
|
||||
if(!server) return {findError("databse_empty_result"), "Invalid port"};
|
||||
if(!server) return command_result{error::server_invalid_id};
|
||||
Command res("");
|
||||
res["server_id"] = server->getServerId();
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandBindingList(Command& cmd) {
|
||||
command_result QueryClient::handleCommandBindingList(Command& cmd) {
|
||||
Command res("");
|
||||
res["ip"] = "0.0.0.0 ";
|
||||
this->sendCommand(res); //TODO maybe list here all bindings from voice & file and query server?
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
//TODO with mapping!
|
||||
CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_virtualserver_snapshot_deploy, 1, true);
|
||||
CMD_RESET_IDLE;
|
||||
|
||||
@ -809,7 +814,7 @@ CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
}
|
||||
|
||||
auto hash = cmd["hash"].string();
|
||||
if(hash.empty()) return {findError("parameter_invalid"), "Invalid hash (not present)"};
|
||||
if(hash.empty()) return command_result{error::parameter_invalid, "Invalid hash (not present)"};
|
||||
debugMessage(this->getServerId(), "Serversnapshot calculated hash: {}", hash);
|
||||
bool mapping = cmd.hasParm("mapping");
|
||||
cmd.disableParm("mapping");
|
||||
@ -821,7 +826,7 @@ CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
auto str = cmd.build().substr(strlen("serversnapshotdeploy "));
|
||||
if(!ignore_hash) {
|
||||
auto buildHash = base64::encode(digest::sha1(str));
|
||||
if(buildHash != hash) return {findError("parameter_invalid"), "Invalid hash (Expected: \"" + hash + "\", Got: \"" + buildHash + "\")"};
|
||||
if(buildHash != hash) return command_result{error::parameter_invalid, "Invalid hash (Expected: \"" + hash + "\", Got: \"" + buildHash + "\")"};
|
||||
}
|
||||
|
||||
unique_lock server_create_lock(serverInstance->getVoiceServerManager()->server_create_lock);
|
||||
@ -853,10 +858,10 @@ CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||
|
||||
res["time"] = duration_cast<milliseconds>(end - start).count();
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_virtualserver_snapshot_create, 1, true);
|
||||
CMD_RESET_IDLE;
|
||||
CMD_REQ_SERVER;
|
||||
@ -868,7 +873,7 @@ CommandResult QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
||||
if(version == -1 && (cmd.hasParm("lagacy") || cmd.hasParm("legacy")))
|
||||
version = 0;
|
||||
if(!serverInstance->getVoiceServerManager()->createServerSnapshot(result, this->server, version, error))
|
||||
return {ErrorType::VSError, error};
|
||||
return command_result{error::vs_critical, error};
|
||||
|
||||
string data = result.build();
|
||||
auto buildHash = base64::encode(digest::sha1(data));
|
||||
@ -877,23 +882,23 @@ CommandResult QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
||||
result[0]["hash"] = buildHash;
|
||||
|
||||
this->sendCommand(result);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
extern bool mainThreadActive;
|
||||
CommandResult QueryClient::handleCommandServerProcessStop(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerProcessStop(Command& cmd) {
|
||||
PERM_CHECKR(permission::b_serverinstance_stop, 1, true);
|
||||
|
||||
if(cmd[0].has("type")) {
|
||||
if(cmd["type"] == "cancel") {
|
||||
auto task = ts::server::scheduledShutdown();
|
||||
if(!task) return {findError("server_is_not_shutting_down"), "There isn't a shutdown scheduled"};
|
||||
if(!task) return command_result{error::server_is_not_shutting_down, "There isn't a shutdown scheduled"};
|
||||
ts::server::cancelShutdown(true);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
} else if(cmd["type"] == "schedule") {
|
||||
if(!cmd[0].has("time")) return {findError("parameter_missing"), "Missing time"};
|
||||
if(!cmd[0].has("time")) return command_result{error::parameter_missing, "Missing time"};
|
||||
ts::server::scheduleShutdown(system_clock::now() + seconds(cmd["time"].as<uint64_t>()), cmd[0].has("msg") ? cmd["msg"].string() : ts::config::messages::applicationStopped);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
}
|
||||
|
||||
@ -904,18 +909,18 @@ CommandResult QueryClient::handleCommandServerProcessStop(Command& cmd) {
|
||||
reason = cmd["reasonmsg"].string();
|
||||
serverInstance->getVoiceServerManager()->shutdownAll(reason);
|
||||
mainThreadActive = false;
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
#define XMACRO_EV(evName0, evSpec0, evName1, evSpec1) \
|
||||
if(cmd["event"].value() == "all" || (cmd["event"].value() == (evName0) && (cmd["specifier"].value() == "all" || cmd["specifier"].value() == (evSpec0)))) \
|
||||
events.push_back({QueryEventGroup::evName1, QueryEventSpecifier::evSpec1});
|
||||
|
||||
inline CommandResult parseEvent(ParameterBulk& cmd, vector<pair<QueryEventGroup, QueryEventSpecifier>>& events){
|
||||
inline bool parseEvent(ParameterBulk& cmd, vector<pair<QueryEventGroup, QueryEventSpecifier>>& events){
|
||||
auto start = events.size();
|
||||
#include "XMacroEventTypes.h"
|
||||
if(start == events.size()) return {findError("parameter_invalid"), "invalid group/specifier"};
|
||||
return CommandResult::Success;
|
||||
if(start == events.size()) return false;
|
||||
return true;
|
||||
}
|
||||
#undef XMACRO_EV
|
||||
|
||||
@ -923,7 +928,7 @@ inline CommandResult parseEvent(ParameterBulk& cmd, vector<pair<QueryEventGroup,
|
||||
#define XMACRO_LAGACY_EV(lagacyName, gr, spec) \
|
||||
if(event == lagacyName) this->toggleEvent(QueryEventGroup::gr, QueryEventSpecifier::spec, true);
|
||||
|
||||
CommandResult QueryClient::handleCommandServerNotifyRegister(Command &cmd) {
|
||||
command_result QueryClient::handleCommandServerNotifyRegister(Command &cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_REQ_PARM("event");
|
||||
CMD_RESET_IDLE;
|
||||
@ -932,17 +937,17 @@ CommandResult QueryClient::handleCommandServerNotifyRegister(Command &cmd) {
|
||||
string event = cmd["event"];
|
||||
std::transform(event.begin(), event.end(), event.begin(), ::tolower);
|
||||
#include "XMacroEventTypes.h"
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
//TODO implement bulk
|
||||
vector<pair<QueryEventGroup, QueryEventSpecifier>> events;
|
||||
//parameter_invalid
|
||||
auto result = parseEvent(cmd[0], events);
|
||||
if(!result) return result;
|
||||
if(!result) return command_result{error::parameter_invalid};
|
||||
for(const auto& ev : events)
|
||||
this->toggleEvent(ev.first, ev.second, true);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
#undef XMACRO_LAGACY_EV
|
||||
|
||||
@ -953,7 +958,7 @@ else if((evName1) == group && (evSpec1) == spec){ \
|
||||
index++; \
|
||||
}
|
||||
|
||||
CommandResult QueryClient::handleCommandServerNotifyList(Command& cmd) {
|
||||
command_result QueryClient::handleCommandServerNotifyList(Command& cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_RESET_IDLE;
|
||||
|
||||
@ -970,16 +975,16 @@ CommandResult QueryClient::handleCommandServerNotifyList(Command& cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
if(index == 0) return {findError("database_empty_result"), ""};
|
||||
if(index == 0) return command_result{error::database_empty_result};
|
||||
this->sendCommand(res);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
#undef XMACRO_EV
|
||||
|
||||
#define XMACRO_LAGACY_EV(lagacyName, gr, spec) \
|
||||
if(event == lagacyName) this->toggleEvent(QueryEventGroup::gr, QueryEventSpecifier::spec, false);
|
||||
|
||||
CommandResult QueryClient::handleCommandServerNotifyUnregister(Command &cmd) {
|
||||
command_result QueryClient::handleCommandServerNotifyUnregister(Command &cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_REQ_PARM("event");
|
||||
CMD_RESET_IDLE;
|
||||
@ -988,15 +993,15 @@ CommandResult QueryClient::handleCommandServerNotifyUnregister(Command &cmd) {
|
||||
string event = cmd["event"];
|
||||
std::transform(event.begin(), event.end(), event.begin(), ::tolower);
|
||||
#include "XMacroEventTypes.h"
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
//TODO implemt bulk
|
||||
vector<pair<QueryEventGroup, QueryEventSpecifier>> events;
|
||||
auto result = parseEvent(cmd[0], events);
|
||||
if(!result) return result;
|
||||
if(!result) return command_result{error::parameter_invalid};
|
||||
for(const auto& ev : events)
|
||||
this->toggleEvent(ev.first, ev.second, false);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
||||
#undef XMACRO_LAGACY_EV
|
@ -1,6 +1,6 @@
|
||||
#ifndef XMACRO_EV
|
||||
#define XMACRO_EV_UNDEF
|
||||
#define XMACRO_EV(a, b, c, d)
|
||||
#ifndef XMACRO_EV
|
||||
#define XMACRO_EV(a, b, c, d)
|
||||
#endif
|
||||
#ifndef XMACRO_LAGACY_EV
|
||||
#define XMACRO_LAGACY_EV_UNDEF
|
||||
|
@ -85,7 +85,7 @@ namespace ts {
|
||||
void send_voice_whisper_packet(const pipes::buffer_view &packet, const VoicePacketFlags &flags) override;
|
||||
|
||||
protected:
|
||||
virtual CommandResult handleCommand(Command &command) override;
|
||||
virtual command_result handleCommand(Command &command) override;
|
||||
|
||||
//Some helper method
|
||||
void sendPingRequest();
|
||||
@ -106,10 +106,10 @@ namespace ts {
|
||||
bool final_disconnected = false;
|
||||
|
||||
//General TS3 manager commands
|
||||
CommandResult handleCommandClientInitIv(Command&);
|
||||
CommandResult handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>&, Command&);
|
||||
CommandResult handleCommandClientInit(Command&) override;
|
||||
CommandResult handleCommandClientDisconnect(Command&);
|
||||
command_result handleCommandClientInitIv(Command&);
|
||||
command_result handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>&, Command&);
|
||||
command_result handleCommandClientInit(Command&) override;
|
||||
command_result handleCommandClientDisconnect(Command&);
|
||||
|
||||
//Locked by finalDisconnect, disconnect and close connection
|
||||
std::shared_ptr<threads::Thread> flushing_thread;
|
||||
|
@ -16,10 +16,10 @@ using namespace ts::protocol;
|
||||
using namespace ts;
|
||||
|
||||
|
||||
CommandResult VoiceClient::handleCommand(ts::Command &command) {
|
||||
command_result VoiceClient::handleCommand(ts::Command &command) {
|
||||
threads::MutexLock l2(this->command_lock);
|
||||
if(this->state == ConnectionState::DISCONNECTED) return CommandResult::NotImplemented;
|
||||
if(!this->voice_server) return CommandResult::NotImplemented;
|
||||
if(this->state == ConnectionState::DISCONNECTED) return command_result{error::client_not_logged_in};
|
||||
if(!this->voice_server) return command_result{error::server_unbound};
|
||||
|
||||
if(this->state == ConnectionState::INIT_HIGH && this->handshake.state == HandshakeState::SUCCEEDED) {
|
||||
if(command.command() == "clientinit")
|
||||
@ -55,7 +55,7 @@ inline bool calculate_security_level(int& result, ecc_key* pubKey, size_t offset
|
||||
return true;
|
||||
}
|
||||
|
||||
CommandResult VoiceClient::handleCommandClientInit(Command &cmd) {
|
||||
command_result VoiceClient::handleCommandClientInit(Command &cmd) {
|
||||
this->crypto.client_init = true;
|
||||
this->connection->acknowledge_handler.reset();
|
||||
|
||||
@ -63,22 +63,22 @@ CommandResult VoiceClient::handleCommandClientInit(Command &cmd) {
|
||||
int securityLevel;
|
||||
if(!calculate_security_level(securityLevel, this->crypto.remote_key.get(), cmd["client_key_offset"])) {
|
||||
logError(this->getServerId(), "[{}] Failed to calculate security level. Error code: {}", CLIENT_STR_LOG_PREFIX, securityLevel);
|
||||
return {ErrorType::VSError};
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
if(securityLevel < 8)
|
||||
return {findError("channel_invalid_security_hash"), "cant calculate security level"};
|
||||
return command_result{error::client_could_not_validate_identity};
|
||||
|
||||
auto requiredLevel = this->getServer()->properties()[property::VIRTUALSERVER_NEEDED_IDENTITY_SECURITY_LEVEL].as<uint8_t>();
|
||||
if(securityLevel < requiredLevel) return {findError("client_could_not_validate_identity"), to_string(requiredLevel)};
|
||||
if(securityLevel < requiredLevel) return command_result{error::client_could_not_validate_identity, to_string(requiredLevel)};
|
||||
}
|
||||
|
||||
this->lastPingResponse = std::chrono::system_clock::now();
|
||||
return SpeakingClient::handleCommandClientInit(cmd);
|
||||
}
|
||||
|
||||
CommandResult VoiceClient::handleCommandClientDisconnect(Command& cmd) {
|
||||
command_result VoiceClient::handleCommandClientDisconnect(Command& cmd) {
|
||||
auto reason = cmd["reasonmsg"].size() > 0 ? cmd["reasonmsg"].as<string>() : "";
|
||||
this->disconnect(VREASON_SERVER_LEFT, reason, nullptr, true);
|
||||
logMessage(this->getServerId(), "{} Got remote disconnect with the reason '{}'", CLIENT_STR_LOG_PREFIX, reason);
|
||||
return CommandResult::Success;
|
||||
return command_result{error::ok};
|
||||
}
|
@ -22,7 +22,7 @@ inline void generate_random(uint8_t *destination, size_t length) {
|
||||
*(destination++) = (uint8_t) rand();
|
||||
}
|
||||
|
||||
ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
this->last_packet_handshake = system_clock::now();
|
||||
|
||||
if(this->state == ConnectionState::CONNECTED) { /* we've a reconnect */
|
||||
@ -31,13 +31,13 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
CLIENT_STR_LOG_PREFIX,
|
||||
duration_cast<milliseconds>(system_clock::now() - this->lastPingResponse).count()
|
||||
);
|
||||
return CommandResult::Success;
|
||||
return ts::command_result{error::ok};
|
||||
} else if(!config::voice::allow_session_reinitialize) {
|
||||
logMessage(this->getServerId(), "{} Client initialized session reconnect and last ping response is older then 5 seconds ({}). Dropping attempt because its not allowed due to config settings",
|
||||
CLIENT_STR_LOG_PREFIX,
|
||||
duration_cast<milliseconds>(system_clock::now() - this->lastPingResponse).count()
|
||||
);
|
||||
return CommandResult::Success;
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
logMessage(this->getServerId(), "{} Client initialized reconnect and last ping response is older then 5 seconds ({}). Allowing attempt",
|
||||
CLIENT_STR_LOG_PREFIX,
|
||||
@ -70,7 +70,7 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
|
||||
/* normal TeamSpeak handling */
|
||||
string clientAlpha = base64::decode(command["alpha"]); //random
|
||||
if(clientAlpha.length() != 10) return {findError("parameter_invalid"), "Invalid alpha"};
|
||||
if(clientAlpha.length() != 10) return ts::command_result{error::parameter_invalid};
|
||||
|
||||
string clientOmega = base64::decode(command["omega"]); //The identity public key
|
||||
string ip = command["ip"];
|
||||
@ -85,7 +85,7 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
auto state = ecc_import((const unsigned char *) clientOmega.data(), clientOmega.length(), this->crypto.remote_key.get());
|
||||
if(state != CRYPT_OK) {
|
||||
this->crypto.remote_key.reset();
|
||||
return {ts::findError("client_could_not_validate_identity"), error_to_string(state)};
|
||||
return ts::command_result{error::client_could_not_validate_identity};
|
||||
}
|
||||
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = base64::encode(digest::sha1(command["omega"].string()));
|
||||
|
||||
@ -115,7 +115,10 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
char signBuffer[signBufferLength];
|
||||
prng_state prngState{};
|
||||
memset(&prngState, 0, sizeof(prngState));
|
||||
if(ecc_sign_hash((u_char*) licenseHash.data(), licenseHash.length(), (u_char*) signBuffer, &signBufferLength, &prngState, find_prng("sprng"), this->getServer()->serverKey()) != CRYPT_OK) return {findError("vs_critical"), "Could not sign license!"};
|
||||
if(ecc_sign_hash((u_char*) licenseHash.data(), licenseHash.length(), (u_char*) signBuffer, &signBufferLength, &prngState, find_prng("sprng"), this->getServer()->serverKey()) != CRYPT_OK) {
|
||||
logError(this->getServerId(), "Failed to sign crypto chain!");
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
auto proof = base64::encode(signBuffer, signBufferLength);
|
||||
|
||||
Command initivexpand2("initivexpand2");
|
||||
@ -134,7 +137,10 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
debugMessage(this->getServerId(), "{} Got non client 3.1 protocol with build timestamp {}", CLIENT_STR_LOG_PREFIX, this->crypto.client_time);
|
||||
|
||||
auto serverOmega = this->getServer()->publicServerKey();
|
||||
if(serverOmega.empty()) return {findError("vs_critical"), "Could not export public key!"};
|
||||
if(serverOmega.empty()) {
|
||||
logError(this->getServerId(), "Failed to export server public key!");
|
||||
return ts::command_result{error::vs_critical};;
|
||||
}
|
||||
|
||||
{
|
||||
Command initivexpand("initivexpand");
|
||||
@ -155,17 +161,17 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
|
||||
string error;
|
||||
if(!this->connection->getCryptHandler()->setupSharedSecret(this->crypto.alpha, this->crypto.beta, this->crypto.remote_key.get(), this->server->serverKey(), error)){
|
||||
this->connection->getCryptHandler()->unblock();
|
||||
debugMessage(this->server->getServerId(), "Could not setup shared secret! (" + error + ")");
|
||||
return {findError("vs_critical"), "Could not setup shared secret"};
|
||||
logError(this->server->getServerId(), "Could not setup shared secret! (" + error + ")");
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
this->connection->getCryptHandler()->unblock();
|
||||
this->crypto.protocol_encrypted = true;
|
||||
}
|
||||
}
|
||||
return CommandResult::Success;
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
|
||||
ts::CommandResult VoiceClient::handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>& packet, Command& cmd) {
|
||||
ts::command_result VoiceClient::handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>& packet, Command& cmd) {
|
||||
this->last_packet_handshake = system_clock::now();
|
||||
debugMessage(this->getServerId(), "{} Got client ek!", CLIENT_STR_LOG_PREFIX);
|
||||
|
||||
@ -176,5 +182,5 @@ ts::CommandResult VoiceClient::handleCommandClientEk(const std::unique_ptr<proto
|
||||
this->connection->acknowledge_handler.reset();
|
||||
this->crypto.protocol_encrypted = true;
|
||||
this->sendAcknowledge(packet->packetId()); //Send the encrypted acknowledge
|
||||
return CommandResult::Success;
|
||||
return ts::command_result{error::ok};
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
#include <algorithm>
|
||||
#include <log/LogUtils.h>
|
||||
#include "../web/WebClient.h"
|
||||
#include "query/command2.h"
|
||||
#include "VoiceClient.h"
|
||||
|
||||
using namespace std;
|
||||
@ -18,28 +17,29 @@ void VoiceClient::handlePacketInit(const unique_ptr<ts::protocol::ClientPacket>
|
||||
//TODO Packet handlers -> move back to voice manager?
|
||||
void VoiceClient::handlePacketCommand(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
||||
std::unique_ptr<Command> command;
|
||||
command_result result{};
|
||||
try {
|
||||
command = make_unique<Command>(Command::parse(packet->data(), true, !ts::config::server::strict_ut8_mode));
|
||||
} catch(std::invalid_argument& ex) {
|
||||
this->notifyError({findError("parameter_convert"), ex.what()});
|
||||
return;
|
||||
} catch(command_malformed_exception& ex) {
|
||||
this->notifyError({findError("parameter_convert"), ex.what()});
|
||||
return;
|
||||
result = command_result{error::parameter_convert, std::string{ex.what()}};
|
||||
goto handle_error;
|
||||
} catch(std::exception& ex) {
|
||||
this->notifyError({findError("parameter_convert"), ex.what()});
|
||||
return;
|
||||
result = command_result{error::parameter_convert, std::string{ex.what()}};
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
if(command->command() == "clientek") {
|
||||
auto result = this->handleCommandClientEk(packet, *command);
|
||||
if(!result)
|
||||
this->notifyError(result);
|
||||
result = this->handleCommandClientEk(packet, *command);
|
||||
if(result.error_code()) goto handle_error;
|
||||
} else if(command->command() == "clientinitiv") {
|
||||
auto result = this->handleCommandClientInitIv(*command);
|
||||
if(!result)
|
||||
this->notifyError(result);
|
||||
result = this->handleCommandClientInitIv(*command);
|
||||
if(result.error_code()) goto handle_error;
|
||||
} else this->handleCommandFull(*command, true);
|
||||
|
||||
return;
|
||||
handle_error:
|
||||
this->notifyError(result);
|
||||
result.release_details();
|
||||
}
|
||||
|
||||
void VoiceClient::handlePacketPing(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
||||
|
@ -232,11 +232,11 @@ bool WebClient::closeConnection(const std::chrono::system_clock::time_point& tim
|
||||
return true;
|
||||
}
|
||||
|
||||
CommandResult WebClient::handleCommand(Command &command) {
|
||||
command_result WebClient::handleCommand(Command &command) {
|
||||
if(this->connectionState() == ConnectionState::INIT_HIGH && this->handshake.state == HandshakeState::SUCCEEDED){
|
||||
if(command.command() == "clientinit") {
|
||||
auto result = this->handleCommandClientInit(command);
|
||||
if(!result)
|
||||
if(result.error_code())
|
||||
this->closeConnection(system_clock::now() + seconds(1));
|
||||
return result;
|
||||
}
|
||||
@ -624,7 +624,7 @@ bool WebClient::disconnect(const std::string &reason) {
|
||||
return this->closeConnection(system_clock::now() + seconds(1));
|
||||
}
|
||||
|
||||
CommandResult WebClient::handleCommandClientInit(Command &command) {
|
||||
command_result WebClient::handleCommandClientInit(Command &command) {
|
||||
return SpeakingClient::handleCommandClientInit(command);
|
||||
}
|
||||
|
||||
|
@ -109,8 +109,8 @@ namespace ts {
|
||||
|
||||
protected:
|
||||
|
||||
CommandResult handleCommand(Command &command) override;
|
||||
CommandResult handleCommandClientInit(Command &command) override;
|
||||
command_result handleCommand(Command &command) override;
|
||||
command_result handleCommandClientInit(Command &command) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
2
shared
2
shared
@ -1 +1 @@
|
||||
Subproject commit 664b73910c99558f9ba14dd2f06dabe67b5f2f2a
|
||||
Subproject commit d42ec40a58892f4c7ff1da6dd4e69df94e2aa848
|
Loading…
Reference in New Issue
Block a user