void TabSupervisor::retranslateUi() { QList<Tab *> tabs; tabs.append(tabServer); tabs.append(tabReplays); tabs.append(tabDeckStorage); tabs.append(tabAdmin); tabs.append(tabUserLists); tabs.append(tabLog); QMapIterator<int, TabRoom *> roomIterator(roomTabs); while (roomIterator.hasNext()) tabs.append(roomIterator.next().value()); QMapIterator<int, TabGame *> gameIterator(gameTabs); while (gameIterator.hasNext()) tabs.append(gameIterator.next().value()); QListIterator<TabGame *> replayIterator(replayTabs); while (replayIterator.hasNext()) tabs.append(replayIterator.next()); QListIterator<TabDeckEditor *> deckEditorIterator(deckEditorTabs); while (deckEditorIterator.hasNext()) tabs.append(deckEditorIterator.next()); QMapIterator<QString, TabMessage *> messageIterator(messageTabs); while (messageIterator.hasNext()) tabs.append(messageIterator.next().value()); for (int i = 0; i < tabs.size(); ++i) if (tabs[i]) { int idx = indexOf(tabs[i]); QString tabText = tabs[i]->getTabText(); setTabText(idx, sanitizeTabName(tabText)); setTabToolTip(idx, sanitizeHtml(tabText)); tabs[i]->retranslateUi(); } }
Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc) { if (authState == NotLoggedIn) return Response::RespLoginNeeded; // We don't need to check whether the user is logged in; persistent games should also work. // The client needs to deal with an empty result list. Response_GetGamesOfUser *re = new Response_GetGamesOfUser; server->roomsLock.lockForRead(); QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->gamesLock.lockForRead(); room->getInfo(*re->add_room_list(), false, true); QListIterator<ServerInfo_Game> gameIterator(room->getGamesOfUser(QString::fromStdString(cmd.user_name()))); while (gameIterator.hasNext()) re->add_game_list()->CopyFrom(gameIterator.next()); room->gamesLock.unlock(); } server->roomsLock.unlock(); rc.setResponseExtension(re); return Response::RespOk; }
IslInterface::~IslInterface() { logger->logMessage("[ISL] session ended", this); flushOutputBuffer(); // As these signals are connected with Qt::QueuedConnection implicitly, // we don't need to worry about them modifying the lists while we're iterating. server->roomsLock.lockForRead(); QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->usersLock.lockForRead(); QMapIterator<QString, ServerInfo_User_Container> roomUsers(room->getExternalUsers()); while (roomUsers.hasNext()) { roomUsers.next(); if (roomUsers.value().getUserInfo()->server_id() == serverId) emit externalRoomUserLeft(room->getId(), roomUsers.key()); } room->usersLock.unlock(); } server->roomsLock.unlock(); server->clientsLock.lockForRead(); QMapIterator<QString, Server_AbstractUserInterface *> extUsers(server->getExternalUsers()); while (extUsers.hasNext()) { extUsers.next(); if (extUsers.value()->getUserInfo()->server_id() == serverId) emit externalUserLeft(extUsers.key()); } server->clientsLock.unlock(); }
void Server::prepareDestroy() { roomsLock.lockForWrite(); QMapIterator<int, Server_Room *> roomIterator(rooms); while (roomIterator.hasNext()) delete roomIterator.next().value(); rooms.clear(); roomsLock.unlock(); }
int Server::getGamesCount() const { int result = 0; QReadLocker locker(&roomsLock); QMapIterator<int, Server_Room *> roomIterator(rooms); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); QReadLocker roomLocker(&room->gamesLock); result += room->getGames().size(); } return result; }
Response::ResponseCode Server_ProtocolHandler::cmdListRooms(const Command_ListRooms & /*cmd*/, ResponseContainer &rc) { if (authState == NotLoggedIn) return Response::RespLoginNeeded; Event_ListRooms event; QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); while (roomIterator.hasNext()) roomIterator.next().value()->getInfo(*event.add_room_list(), false); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); acceptsRoomListChanges = true; return Response::RespOk; }
ResponseCode Server_ProtocolHandler::cmdListRooms(Command_ListRooms * /*cmd*/, CommandContainer *cont) { if (authState == PasswordWrong) return RespLoginNeeded; QList<ServerInfo_Room *> eventRoomList; QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); while (roomIterator.hasNext()) eventRoomList.append(roomIterator.next().value()->getInfo(false)); cont->enqueueItem(new Event_ListRooms(eventRoomList)); acceptsRoomListChanges = true; return RespOk; }
// This function must only be called from the thread this object lives in. // The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock). void Server_ProtocolHandler::prepareDestroy() { if (deleted) return; deleted = true; QMapIterator<int, Server_Room *> roomIterator(rooms); while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); QMap<int, QPair<int, int> > tempGames(getGames()); server->roomsLock.lockForRead(); QMapIterator<int, QPair<int, int> > gameIterator(tempGames); while (gameIterator.hasNext()) { gameIterator.next(); Server_Room *r = server->getRooms().value(gameIterator.value().first); if (!r) continue; r->gamesLock.lockForRead(); Server_Game *g = r->getGames().value(gameIterator.key()); if (!g) { r->gamesLock.unlock(); continue; } g->gameMutex.lock(); Server_Player *p = g->getPlayers().value(gameIterator.value().second); if (!p) { g->gameMutex.unlock(); r->gamesLock.unlock(); continue; } p->disconnectClient(); g->gameMutex.unlock(); r->gamesLock.unlock(); } server->roomsLock.unlock(); server->removeClient(this); deleteLater(); }
void Server::prepareDestroy() { // dirty :( if (threaded) { clientsLock.lockForRead(); for (int i = 0; i < clients.size(); ++i) QMetaObject::invokeMethod(clients.at(i), "prepareDestroy", Qt::QueuedConnection); clientsLock.unlock(); bool done = false; class SleeperThread : public QThread { public: static void msleep(unsigned long msecs) { QThread::usleep(msecs); } }; do { SleeperThread::msleep(10); clientsLock.lockForRead(); if (clients.isEmpty()) done = true; clientsLock.unlock(); } while (!done); } else { // no locking is needed in unthreaded mode while (!clients.isEmpty()) clients.first()->prepareDestroy(); } roomsLock.lockForWrite(); QMapIterator<int, Server_Room *> roomIterator(rooms); while (roomIterator.hasNext()) delete roomIterator.next().value(); rooms.clear(); roomsLock.unlock(); }
Server_ProtocolHandler::~Server_ProtocolHandler() { // The socket has to be removed from the server's list before it is removed from the game's list // so it will not receive the game update event. server->removeClient(this); QMapIterator<int, Server_Room *> roomIterator(rooms); while (roomIterator.hasNext()) roomIterator.next().value()->removeClient(this); QMapIterator<int, QPair<Server_Game *, Server_Player *> > gameIterator(games); while (gameIterator.hasNext()) { gameIterator.next(); Server_Game *g = gameIterator.value().first; Server_Player *p = gameIterator.value().second; if (authState == UnknownUser) g->removePlayer(p); else p->setProtocolHandler(0); } delete userInfo; }
void IslInterface::initServer() { socket->setSocketDescriptor(socketDescriptor); logger->logMessage(QString("[ISL] incoming connection: %1").arg(socket->peerAddress().toString())); QList<ServerProperties> serverList = server->getServerList(); int listIndex = -1; for (int i = 0; i < serverList.size(); ++i) if (serverList[i].address == socket->peerAddress()) { listIndex = i; break; } if (listIndex == -1) { logger->logMessage(QString("[ISL] address %1 unknown, terminating connection").arg(socket->peerAddress().toString())); deleteLater(); return; } socket->startServerEncryption(); if (!socket->waitForEncrypted(5000)) { QList<QSslError> sslErrors(socket->sslErrors()); if (sslErrors.isEmpty()) qDebug() << "[ISL] SSL handshake timeout, terminating connection"; else qDebug() << "[ISL] SSL errors:" << sslErrors; deleteLater(); return; } if (serverList[listIndex].cert == socket->peerCertificate()) logger->logMessage(QString("[ISL] Peer authenticated as " + serverList[listIndex].hostname)); else { logger->logMessage(QString("[ISL] Authentication failed, terminating connection")); deleteLater(); return; } serverId = serverList[listIndex].id; Event_ServerCompleteList event; event.set_server_id(server->getServerId()); server->clientsLock.lockForRead(); QMapIterator<QString, Server_ProtocolHandler *> userIterator(server->getUsers()); while (userIterator.hasNext()) event.add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(true, true)); server->clientsLock.unlock(); server->roomsLock.lockForRead(); QMapIterator<int, Server_Room *> roomIterator(server->getRooms()); while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->usersLock.lockForRead(); room->gamesLock.lockForRead(); room->getInfo(*event.add_room_list(), true, true, false, false); } IslMessage message; message.set_message_type(IslMessage::SESSION_EVENT); SessionEvent *sessionEvent = message.mutable_session_event(); sessionEvent->GetReflection()->MutableMessage(sessionEvent, event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(event); server->islLock.lockForWrite(); if (server->islConnectionExists(serverId)) { qDebug() << "[ISL] Duplicate connection to #" << serverId << "terminating connection"; deleteLater(); } else { transmitMessage(message); server->addIslInterface(serverId, this); } server->islLock.unlock(); roomIterator.toFront(); while (roomIterator.hasNext()) { roomIterator.next(); roomIterator.value()->gamesLock.unlock(); roomIterator.value()->usersLock.unlock(); } server->roomsLock.unlock(); }