Using one global event loop for the query and web client
This commit is contained in:
@@ -22,100 +22,120 @@ bool VirtualServer::registerClient(shared_ptr<ConnectedClient> client) {
|
||||
sassert(client);
|
||||
|
||||
{
|
||||
lock_guard lock(this->clients.lock);
|
||||
std::lock_guard clients_lock{this->clients_mutex};
|
||||
if(client->getClientId() > 0) {
|
||||
logCritical(this->getServerId(), "Client {} ({}|{}) has been already registered!", client->getDisplayName(), client->getClientId(), client->getUid());
|
||||
return false;
|
||||
}
|
||||
|
||||
ClientId client_id = 0;
|
||||
ClientId max_client_id = this->clients.clients.size();
|
||||
|
||||
while(client_id < max_client_id && this->clients.clients[client_id])
|
||||
ClientId client_id{0};
|
||||
while(this->clients.count(client_id)) {
|
||||
client_id++;
|
||||
if(client_id == max_client_id)
|
||||
this->clients.clients.push_back(client);
|
||||
else
|
||||
this->clients.clients[client_id] = client;
|
||||
this->clients.count++;
|
||||
}
|
||||
|
||||
this->clients.emplace(client_id, client);
|
||||
client->setClientId(client_id);
|
||||
}
|
||||
|
||||
{
|
||||
lock_guard lock(this->client_nickname_lock);
|
||||
std::lock_guard lock{this->client_nickname_lock};
|
||||
|
||||
auto login_name = client->getDisplayName();
|
||||
while(login_name.length() < 3)
|
||||
login_name += ".";
|
||||
|
||||
if(client->getExternalType() == ClientType::CLIENT_TEAMSPEAK)
|
||||
if(client->getExternalType() == ClientType::CLIENT_TEAMSPEAK) {
|
||||
client->properties()[property::CLIENT_LOGIN_NAME] = login_name;
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectedClient> found_client = nullptr;
|
||||
while(login_name.length() < 3) {
|
||||
login_name += ".";
|
||||
}
|
||||
|
||||
auto client_name = login_name;
|
||||
size_t counter = 0;
|
||||
std::shared_ptr<ConnectedClient> found_client{nullptr};
|
||||
auto registered_clients = this->getClients();
|
||||
|
||||
auto client_name{login_name};
|
||||
size_t counter{0};
|
||||
|
||||
{
|
||||
lock_guard clients_lock(this->clients.lock);
|
||||
while(true) {
|
||||
for(auto& _client : this->clients.clients) {
|
||||
if(!_client) continue;
|
||||
|
||||
if(_client->getDisplayName() == client_name && _client != client)
|
||||
for(auto& _client : registered_clients) {
|
||||
if(_client->getDisplayName() == client_name && _client != client) {
|
||||
goto increase_name;
|
||||
}
|
||||
}
|
||||
goto nickname_valid;
|
||||
|
||||
increase_name:
|
||||
client_name = login_name + to_string(++counter);
|
||||
client_name = login_name + std::to_string(++counter);
|
||||
}
|
||||
}
|
||||
|
||||
nickname_valid:
|
||||
client->setDisplayName(client_name);
|
||||
}
|
||||
|
||||
switch(client->getType()) {
|
||||
case ClientType::CLIENT_TEAMSPEAK:
|
||||
case ClientType::CLIENT_TEASPEAK:
|
||||
case ClientType::CLIENT_WEB:
|
||||
this->properties()[property::VIRTUALSERVER_CLIENT_CONNECTIONS].increment_by<uint64_t>(1); //increase manager connections
|
||||
this->properties()[property::VIRTUALSERVER_LAST_CLIENT_CONNECT] = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
|
||||
break;
|
||||
|
||||
case ClientType::CLIENT_QUERY:
|
||||
this->properties()[property::VIRTUALSERVER_LAST_QUERY_CONNECT] = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
|
||||
this->properties()[property::VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS].increment_by<uint64_t>(1); //increase manager connections
|
||||
break;
|
||||
|
||||
case ClientType::CLIENT_MUSIC:
|
||||
case ClientType::CLIENT_INTERNAL:
|
||||
break;
|
||||
|
||||
|
||||
if(client->getType() == ClientType::CLIENT_TEAMSPEAK || client->getType() == ClientType::CLIENT_WEB) {
|
||||
this->properties()[property::VIRTUALSERVER_CLIENT_CONNECTIONS].increment_by<uint64_t>(1); //increase manager connections
|
||||
this->properties()[property::VIRTUALSERVER_LAST_CLIENT_CONNECT] = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
else if(client->getType() == ClientType::CLIENT_QUERY) {
|
||||
this->properties()[property::VIRTUALSERVER_LAST_QUERY_CONNECT] = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
|
||||
this->properties()[property::VIRTUALSERVER_QUERY_CLIENT_CONNECTIONS].increment_by<uint64_t>(1); //increase manager connections
|
||||
case ClientType::MAX:
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VirtualServer::unregisterClient(shared_ptr<ConnectedClient> cl, std::string reason, std::unique_lock<std::shared_mutex>& chan_tree_lock) {
|
||||
if(cl->getType() == ClientType::CLIENT_TEAMSPEAK || cl->getType() == ClientType::CLIENT_TEASPEAK || cl->getType() == ClientType::CLIENT_WEB) {
|
||||
sassert(cl->state == ConnectionState::DISCONNECTED);
|
||||
bool VirtualServer::unregisterClient(shared_ptr<ConnectedClient> client, std::string reason, std::unique_lock<std::shared_mutex>& chan_tree_lock) {
|
||||
if(client->getType() == ClientType::CLIENT_TEAMSPEAK || client->getType() == ClientType::CLIENT_TEASPEAK || client->getType() == ClientType::CLIENT_WEB) {
|
||||
sassert(client->state == ConnectionState::DISCONNECTED);
|
||||
}
|
||||
|
||||
auto client_id = cl->getClientId();
|
||||
if(client_id == 0) {
|
||||
return false; /* not registered */
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
lock_guard lock(this->clients.lock);
|
||||
if(client_id >= this->clients.clients.size()) {
|
||||
logCritical(this->getServerId(), "Client {} ({}|{}) has been registered, but client id exceed client id! Failed to unregister client.", cl->getDisplayName(), client_id, cl->getUid());
|
||||
} else {
|
||||
auto& client_container = this->clients.clients[client_id];
|
||||
if(client_container != cl) {
|
||||
logCritical(this->getServerId(), "Client {} ({}|{}) has been registered, but container hasn't client set! Failed to unregister client.", cl->getDisplayName(), client_id, cl->getUid());
|
||||
} else {
|
||||
client_container.reset();
|
||||
this->clients.count--;
|
||||
}
|
||||
if(!chan_tree_lock.owns_lock()) {
|
||||
chan_tree_lock.lock();
|
||||
}
|
||||
|
||||
if(client->currentChannel) {
|
||||
//We dont have to make him invisible if he hasnt even a channel
|
||||
this->client_move(client, nullptr, nullptr, reason, ViewReasonId::VREASON_SERVER_LEFT, false, chan_tree_lock);
|
||||
}
|
||||
|
||||
chan_tree_lock.unlock();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard clients_lock{this->clients_mutex};
|
||||
auto client_id = client->getClientId();
|
||||
if(client_id == 0) {
|
||||
return false; /* not registered */
|
||||
}
|
||||
|
||||
if(!this->clients.erase(client_id)) {
|
||||
client->setClientId(0);
|
||||
logError(this->getServerId(), "Tried to unregister a not registered client {}/{} ({})", client->getDisplayName(), client->getUid(), client_id);
|
||||
return false;
|
||||
}
|
||||
client->setClientId(0);
|
||||
}
|
||||
|
||||
auto current_time_seconds = std::chrono::duration_cast<seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
switch(cl->getType()) {
|
||||
switch(client->getType()) {
|
||||
case ClientType::CLIENT_TEAMSPEAK:
|
||||
case ClientType::CLIENT_TEASPEAK:
|
||||
case ClientType::CLIENT_WEB:
|
||||
@@ -134,65 +154,20 @@ bool VirtualServer::unregisterClient(shared_ptr<ConnectedClient> cl, std::string
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
if(!chan_tree_lock.owns_lock()) {
|
||||
chan_tree_lock.lock();
|
||||
}
|
||||
|
||||
if(cl->currentChannel) {
|
||||
//We dont have to make him invisible if he hasnt even a channel
|
||||
this->client_move(cl, nullptr, nullptr, reason, ViewReasonId::VREASON_SERVER_LEFT, false, chan_tree_lock);
|
||||
}
|
||||
}
|
||||
|
||||
serverInstance->databaseHelper()->saveClientPermissions(this->ref(), cl->getClientDatabaseId(), cl->clientPermissions);
|
||||
cl->setClientId(0);
|
||||
serverInstance->databaseHelper()->saveClientPermissions(this->ref(), client->getClientDatabaseId(), client->clientPermissions);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VirtualServer::registerInternalClient(std::shared_ptr<ConnectedClient> client) {
|
||||
client->state = ConnectionState::CONNECTED;
|
||||
{
|
||||
lock_guard lock(this->clients.lock);
|
||||
if(client->getClientId() > 0) {
|
||||
logCritical(this->getServerId(), "Internal client {} ({}|{}) has been already registered!", client->getDisplayName(), client->getClientId(), client->getUid());
|
||||
return;
|
||||
}
|
||||
|
||||
ClientId client_id = 0;
|
||||
ClientId max_client_id = this->clients.clients.size();
|
||||
while(client_id < max_client_id && this->clients.clients[client_id])
|
||||
client_id++;
|
||||
if(client_id == max_client_id)
|
||||
this->clients.clients.push_back(client);
|
||||
else
|
||||
this->clients.clients[client_id] = client;
|
||||
|
||||
this->clients.clients[client_id] = client;
|
||||
this->clients.count++;
|
||||
client->setClientId(client_id);
|
||||
}
|
||||
this->registerClient(client);
|
||||
}
|
||||
|
||||
void VirtualServer::unregisterInternalClient(std::shared_ptr<ConnectedClient> client) {
|
||||
client->state = ConnectionState::DISCONNECTED;
|
||||
|
||||
{
|
||||
auto client_id = client->getClientId();
|
||||
|
||||
lock_guard lock(this->clients.lock);
|
||||
if(client_id >= this->clients.clients.size()) {
|
||||
logCritical(this->getServerId(), "Client {} ({}|{}) has been registered, but client id exceed client id! Failed to unregister internal client.", client->getDisplayName(), client_id, client->getUid());
|
||||
} else {
|
||||
auto& client_container = this->clients.clients[client_id];
|
||||
if(client_container != client) {
|
||||
logCritical(this->getServerId(), "Client {} ({}|{}) has been registered, but container hasn't client set! Failed to unregister internal client.", client->getDisplayName(), client_id, client->getUid());
|
||||
} else {
|
||||
this->clients.count--;
|
||||
client_container.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
std::unique_lock tree_lock{this->channel_tree_mutex};
|
||||
this->unregisterClient(client, "internal disconnect", tree_lock);
|
||||
}
|
||||
|
||||
bool VirtualServer::assignDefaultChannel(const shared_ptr<ConnectedClient>& client, bool join) {
|
||||
|
||||
Reference in New Issue
Block a user