Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.session_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const SessionCommand &sc = cont.session_command(i); const int num = getPbExtension(sc); if (num != SessionCommand::PING) { // don't log ping commands if (num == SessionCommand::LOGIN) { // log login commands, but hide passwords SessionCommand debugSc(sc); debugSc.MutableExtension(Command_Login::ext)->clear_password(); logDebugMessage(QString::fromStdString(debugSc.ShortDebugString())); } else logDebugMessage(QString::fromStdString(sc.ShortDebugString())); } switch ((SessionCommand::SessionCommandType) num) { case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break; case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break; case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc); break; case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break; case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break; case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break; case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc); break; case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc); break; default: resp = processExtendedSessionCommand(num, sc, rc); } if (resp != Response::RespOk) finalResponseCode = resp; } return finalResponseCode; }
PendingCommand *AbstractClient::prepareAdminCommand(const ::google::protobuf::Message &cmd) { CommandContainer cont; AdminCommand *c = cont.add_admin_command(); c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd); return new PendingCommand(cont); }
Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { if (authState == NotLoggedIn) return Response::RespLoginNeeded; QReadLocker locker(&server->roomsLock); Server_Room *room = rooms.value(cont.room_id(), 0); if (!room) return Response::RespNotInRoom; Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.room_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const RoomCommand &sc = cont.room_command(i); const int num = getPbExtension(sc); logDebugMessage(QString::fromStdString(sc.ShortDebugString())); switch ((RoomCommand::RoomCommandType) num) { case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break; case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc); break; case RoomCommand::CREATE_GAME: resp = cmdCreateGame(sc.GetExtension(Command_CreateGame::ext), room, rc); break; case RoomCommand::JOIN_GAME: resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc); break; } if (resp != Response::RespOk) finalResponseCode = resp; } return finalResponseCode; }
void ServerSocketInterface::processProtocolItem(ProtocolItem *item) { CommandContainer *cont = qobject_cast<CommandContainer *>(item); if (!cont) sendProtocolItem(new ProtocolResponse(cont->getCmdId(), RespInvalidCommand)); else processCommandContainer(cont); }
void IslInterface::processRoomCommand(const CommandContainer &cont, qint64 sessionId) { for (int i = 0; i < cont.room_command_size(); ++i) { const RoomCommand &roomCommand = cont.room_command(i); switch (static_cast<RoomCommand::RoomCommandType>(getPbExtension(roomCommand))) { case RoomCommand::JOIN_GAME: roomCommand_JoinGame(roomCommand.GetExtension(Command_JoinGame::ext), cont.cmd_id(), cont.room_id(), sessionId); default: ; } } }
void Server::sendIsl_RoomCommand(const CommandContainer &item, int serverId, qint64 sessionId, int roomId) { IslMessage msg; msg.set_message_type(IslMessage::ROOM_COMMAND_CONTAINER); msg.set_session_id(sessionId); CommandContainer *cont = msg.mutable_room_command(); cont->CopyFrom(item); cont->set_room_id(roomId); emit sigSendIslMessage(msg, serverId); }
void AbstractClient::processProtocolItem(ProtocolItem *item) { ProtocolResponse *response = qobject_cast<ProtocolResponse *>(item); if (response) { CommandContainer *cmdCont = pendingCommands.value(response->getCmdId(), 0); if (!cmdCont) return; pendingCommands.remove(cmdCont->getCmdId()); cmdCont->processResponse(response); if (response->getReceiverMayDelete()) delete response; cmdCont->deleteLater(); return; } GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item); if (genericEvent) { switch (genericEvent->getItemId()) { case ItemId_Event_UserJoined: emit userJoinedEventReceived(qobject_cast<Event_UserJoined *>(item)); break; case ItemId_Event_UserLeft: emit userLeftEventReceived(qobject_cast<Event_UserLeft *>(item)); break; case ItemId_Event_ServerMessage: emit serverMessageEventReceived(qobject_cast<Event_ServerMessage *>(item)); break; case ItemId_Event_ListRooms: emit listRoomsEventReceived(qobject_cast<Event_ListRooms *>(item)); break; case ItemId_Event_GameJoined: emit gameJoinedEventReceived(qobject_cast<Event_GameJoined *>(item)); break; case ItemId_Event_Message: emit messageEventReceived(qobject_cast<Event_Message *>(item)); break; } if (genericEvent->getReceiverMayDelete()) delete genericEvent; return; } GameEventContainer *gameEventContainer = qobject_cast<GameEventContainer *>(item); if (gameEventContainer) { emit gameEventContainerReceived(gameEventContainer); if (gameEventContainer->getReceiverMayDelete()) delete gameEventContainer; return; } RoomEvent *roomEvent = qobject_cast<RoomEvent *>(item); if (roomEvent) { emit roomEventReceived(roomEvent); if (roomEvent->getReceiverMayDelete()) delete roomEvent; return; } }
void UserContextMenu::gamesOfUserReceived(const Response &resp, const CommandContainer &commandContainer) { const Response_GetGamesOfUser &response = resp.GetExtension(Response_GetGamesOfUser::ext); const Command_GetGamesOfUser &cmd = commandContainer.session_command(0).GetExtension(Command_GetGamesOfUser::ext); QMap<int, GameTypeMap> gameTypeMap; QMap<int, QString> roomMap; const int roomListSize = response.room_list_size(); for (int i = 0; i < roomListSize; ++i) { const ServerInfo_Room &roomInfo = response.room_list(i); roomMap.insert(roomInfo.room_id(), QString::fromStdString(roomInfo.name())); GameTypeMap tempMap; const int gameTypeListSize = roomInfo.gametype_list_size(); for (int j = 0; j < gameTypeListSize; ++j) { const ServerInfo_GameType &gameTypeInfo = roomInfo.gametype_list(j); tempMap.insert(gameTypeInfo.game_type_id(), QString::fromStdString(gameTypeInfo.description())); } gameTypeMap.insert(roomInfo.room_id(), tempMap); } GameSelector *selector = new GameSelector(client, tabSupervisor, 0, roomMap, gameTypeMap, false, false); const int gameListSize = response.game_list_size(); for (int i = 0; i < gameListSize; ++i) selector->processGameInfo(response.game_list(i)); selector->setWindowTitle(tr("%1's games").arg(QString::fromStdString(cmd.user_name()))); selector->setMinimumWidth(800); selector->setAttribute(Qt::WA_DeleteOnClose); selector->show(); }
void RemoteClient::sendCommandContainer(const CommandContainer &cont) { QByteArray buf; unsigned int size = cont.ByteSize(); #ifdef QT_DEBUG qDebug() << "OUT" << size << QString::fromStdString(cont.ShortDebugString()); #endif buf.resize(size + 4); cont.SerializeToArray(buf.data() + 4, size); buf.data()[3] = (unsigned char) size; buf.data()[2] = (unsigned char) (size >> 8); buf.data()[1] = (unsigned char) (size >> 16); buf.data()[0] = (unsigned char) (size >> 24); socket->write(buf); }
void TabReplays::deleteRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer) { if (r.response_code() != Response::RespOk) return; const Command_ReplayDeleteMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayDeleteMatch::ext); serverDirView->removeMatchInfo(cmd.game_id()); }
void TabDeckStorage::newFolderFinished(const Response &response, const CommandContainer &commandContainer) { if (response.response_code() != Response::RespOk) return; const Command_DeckNewDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckNewDir::ext); serverDirView->addFolderToTree(QString::fromStdString(cmd.dir_name()), serverDirView->getNodeByPath(QString::fromStdString(cmd.path()))); }
void Server_ProtocolHandler::processCommandContainer(const CommandContainer &cont) { // Command processing must be disabled after prepareDestroy() has been called. if (deleted) return; lastDataReceived = timeRunning; ResponseContainer responseContainer(cont.has_cmd_id() ? cont.cmd_id() : -1); Response::ResponseCode finalResponseCode; if (cont.game_command_size()) finalResponseCode = processGameCommandContainer(cont, responseContainer); else if (cont.room_command_size()) finalResponseCode = processRoomCommandContainer(cont, responseContainer); else if (cont.session_command_size()) finalResponseCode = processSessionCommandContainer(cont, responseContainer); else if (cont.moderator_command_size()) finalResponseCode = processModeratorCommandContainer(cont, responseContainer); else if (cont.admin_command_size()) finalResponseCode = processAdminCommandContainer(cont, responseContainer); else finalResponseCode = Response::RespInvalidCommand; if ((finalResponseCode != Response::RespNothing)) sendResponseContainer(responseContainer, finalResponseCode); }
void Server::externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId) { // This function is always called from the main thread via signal/slot. try { ResponseContainer responseContainer(cont.cmd_id()); Response::ResponseCode finalResponseCode = Response::RespOk; QReadLocker roomsLocker(&roomsLock); Server_Room *room = rooms.value(cont.room_id()); if (!room) { qDebug() << "externalGameCommandContainerReceived: room id=" << cont.room_id() << "not found"; throw Response::RespNotInRoom; } QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(cont.game_id()); if (!game) { qDebug() << "externalGameCommandContainerReceived: game id=" << cont.game_id() << "not found"; throw Response::RespNotInRoom; } QMutexLocker gameLocker(&game->gameMutex); Server_Player *player = game->getPlayers().value(playerId); if (!player) { qDebug() << "externalGameCommandContainerReceived: player id=" << playerId << "not found"; throw Response::RespNotInRoom; } GameEventStorage ges; for (int i = cont.game_command_size() - 1; i >= 0; --i) { const GameCommand &sc = cont.game_command(i); qDebug() << "[ISL]" << QString::fromStdString(sc.ShortDebugString()); Response::ResponseCode resp = player->processGameCommand(sc, responseContainer, ges); if (resp != Response::RespOk) finalResponseCode = resp; } ges.sendToGame(game); if (finalResponseCode != Response::RespNothing) { player->playerMutex.lock(); player->getUserInterface()->sendResponseContainer(responseContainer, finalResponseCode); player->playerMutex.unlock(); } } catch (Response::ResponseCode code) { Response response; response.set_cmd_id(cont.cmd_id()); response.set_response_code(code); sendIsl_Response(response, serverId, sessionId); } }
void TabDeckStorage::deleteFolderFinished(const Response &response, const CommandContainer &commandContainer) { if (response.response_code() != Response::RespOk) return; const Command_DeckDelDir &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDelDir::ext); RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeByPath(QString::fromStdString(cmd.path())); if (toDelete) serverDirView->removeNode(toDelete); }
void TabDeckStorage::deleteDeckFinished(const Response &response, const CommandContainer &commandContainer) { if (response.response_code() != Response::RespOk) return; const Command_DeckDel &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDel::ext); RemoteDeckList_TreeModel::Node *toDelete = serverDirView->getNodeById(cmd.deck_id()); if (toDelete) serverDirView->removeNode(toDelete); }
void TabDeckStorage::uploadFinished(const Response &r, const CommandContainer &commandContainer) { if (r.response_code() != Response::RespOk) return; const Response_DeckUpload &resp = r.GetExtension(Response_DeckUpload::ext); const Command_DeckUpload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckUpload::ext); serverDirView->addFileToTree(resp.new_file(), serverDirView->getNodeByPath(QString::fromStdString(cmd.path()))); }
Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { if (!userInfo) return Response::RespLoginNeeded; if (!(userInfo->user_level() & ServerInfo_User::IsAdmin)) return Response::RespLoginNeeded; Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.admin_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const AdminCommand &sc = cont.admin_command(i); const int num = getPbExtension(sc); logDebugMessage(QString::fromStdString(sc.ShortDebugString())); resp = processExtendedAdminCommand(num, sc, rc); if (resp != Response::RespOk) finalResponseCode = resp; } return finalResponseCode; }
void TabReplays::keepRemoteReplayFinished(const Response &r, const CommandContainer &commandContainer) { if (r.response_code() != Response::RespOk) return; const Command_ReplayModifyMatch &cmd = commandContainer.session_command(0).GetExtension(Command_ReplayModifyMatch::ext); ServerInfo_ReplayMatch temp; temp.set_do_not_hide(cmd.do_not_hide()); serverDirView->updateMatchInfo(cmd.game_id(), temp); }
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { if (authState == NotLoggedIn) return Response::RespLoginNeeded; QMap<int, QPair<int, int> > gameMap = getGames(); if (!gameMap.contains(cont.game_id())) return Response::RespNotInRoom; const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id()); QReadLocker roomsLocker(&server->roomsLock); Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first); if (!room) return Response::RespNotInRoom; QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(cont.game_id()); if (!game) { if (room->getExternalGames().contains(cont.game_id())) { server->sendIsl_GameCommand(cont, room->getExternalGames().value(cont.game_id()).server_id(), userInfo->session_id(), roomIdAndPlayerId.first, roomIdAndPlayerId.second ); return Response::RespNothing; } return Response::RespNotInRoom; } QMutexLocker gameLocker(&game->gameMutex); Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second); if (!player) return Response::RespNotInRoom; GameEventStorage ges; Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.game_command_size() - 1; i >= 0; --i) { const GameCommand &sc = cont.game_command(i); logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString())); Response::ResponseCode resp = player->processGameCommand(sc, rc, ges); if (resp != Response::RespOk) finalResponseCode = resp; } ges.sendToGame(game); return finalResponseCode; }
void TabDeckStorage::openRemoteDeckFinished(const Response &r, const CommandContainer &commandContainer) { if (r.response_code() != Response::RespOk) return; const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext); const Command_DeckDownload &cmd = commandContainer.session_command(0).GetExtension(Command_DeckDownload::ext); DeckLoader loader; if (!loader.loadFromRemote(QString::fromStdString(resp.deck()), cmd.deck_id())) return; emit openDeckEditor(&loader); }
void ServerSocketInterface::readClient() { QByteArray data = socket->readAll(); servatrice->incRxBytes(data.size()); inputBuffer.append(data); do { if (!messageInProgress) { if (inputBuffer.size() >= 4) { messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24) + (((quint32) (unsigned char) inputBuffer[1]) << 16) + (((quint32) (unsigned char) inputBuffer[2]) << 8) + ((quint32) (unsigned char) inputBuffer[3]); inputBuffer.remove(0, 4); messageInProgress = true; } else return; } if (inputBuffer.size() < messageLength) return; CommandContainer newCommandContainer; newCommandContainer.ParseFromArray(inputBuffer.data(), messageLength); inputBuffer.remove(0, messageLength); messageInProgress = false; // dirty hack to make v13 client display the correct error message if (handshakeStarted) processCommandContainer(newCommandContainer); else if (!newCommandContainer.has_cmd_id()) { handshakeStarted = true; if (!initSession()) prepareDestroy(); } // end of hack } while (!inputBuffer.isEmpty()); }
void ServerSocketInterface::readClient() { QByteArray data = socket->readAll(); servatrice->incRxBytes(data.size()); inputBuffer.append(data); do { if (!messageInProgress) { if (inputBuffer.size() >= 4) { messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24) + (((quint32) (unsigned char) inputBuffer[1]) << 16) + (((quint32) (unsigned char) inputBuffer[2]) << 8) + ((quint32) (unsigned char) inputBuffer[3]); inputBuffer.remove(0, 4); messageInProgress = true; } else return; } if (inputBuffer.size() < messageLength) return; CommandContainer newCommandContainer; try { newCommandContainer.ParseFromArray(inputBuffer.data(), messageLength); } catch(std::exception &e) { qDebug() << "Caught std::exception in" << __FILE__ << __LINE__ << #ifdef _MSC_VER // Visual Studio __FUNCTION__; #else __PRETTY_FUNCTION__; #endif qDebug() << "Exception:" << e.what(); qDebug() << "Message coming from:" << getAddress(); qDebug() << "Message length:" << messageLength; qDebug() << "Message content:" << inputBuffer.toHex(); } catch(...) { qDebug() << "Unhandled exception in" << __FILE__ << __LINE__ << #ifdef _MSC_VER // Visual Studio __FUNCTION__; #else __PRETTY_FUNCTION__; #endif qDebug() << "Message coming from:" << getAddress(); } inputBuffer.remove(0, messageLength); messageInProgress = false; // dirty hack to make v13 client display the correct error message if (handshakeStarted) processCommandContainer(newCommandContainer); else if (!newCommandContainer.has_cmd_id()) { handshakeStarted = true; if (!initSession()) prepareDestroy(); } // end of hack } while (!inputBuffer.isEmpty()); }
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { static QList<GameCommand::GameCommandType> antifloodCommandsWhiteList = QList<GameCommand::GameCommandType>() // draw/undo card draw (example: drawing 10 cards one by one from the deck) << GameCommand::DRAW_CARDS << GameCommand::UNDO_DRAW // create, delete arrows (example: targeting with 10 cards during an attack) << GameCommand::CREATE_ARROW << GameCommand::DELETE_ARROW // set card attributes (example: tapping 10 cards at once) << GameCommand::SET_CARD_ATTR // increment / decrement counter (example: -10 life points one by one) << GameCommand::INC_COUNTER // mulling lots of hands in a row << GameCommand::MULLIGAN // allows a user to sideboard without receiving flooding message << GameCommand::MOVE_CARD; if (authState == NotLoggedIn) return Response::RespLoginNeeded; QMap<int, QPair<int, int> > gameMap = getGames(); if (!gameMap.contains(cont.game_id())) return Response::RespNotInRoom; const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id()); QReadLocker roomsLocker(&server->roomsLock); Server_Room *room = server->getRooms().value(roomIdAndPlayerId.first); if (!room) return Response::RespNotInRoom; QReadLocker roomGamesLocker(&room->gamesLock); Server_Game *game = room->getGames().value(cont.game_id()); if (!game) { if (room->getExternalGames().contains(cont.game_id())) { server->sendIsl_GameCommand(cont, room->getExternalGames().value(cont.game_id()).server_id(), userInfo->session_id(), roomIdAndPlayerId.first, roomIdAndPlayerId.second ); return Response::RespNothing; } return Response::RespNotInRoom; } QMutexLocker gameLocker(&game->gameMutex); Server_Player *player = game->getPlayers().value(roomIdAndPlayerId.second); if (!player) return Response::RespNotInRoom; int commandCountingInterval = server->getCommandCountingInterval(); int maxCommandCountPerInterval = server->getMaxCommandCountPerInterval(); GameEventStorage ges; Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.game_command_size() - 1; i >= 0; --i) { const GameCommand &sc = cont.game_command(i); logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString())); if (commandCountingInterval > 0) { int totalCount = 0; if (commandCountOverTime.isEmpty()) commandCountOverTime.prepend(0); if(!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType) getPbExtension(sc))) ++commandCountOverTime[0]; for (int i = 0; i < commandCountOverTime.size(); ++i) totalCount += commandCountOverTime[i]; if (totalCount > maxCommandCountPerInterval) return Response::RespChatFlood; } Response::ResponseCode resp = player->processGameCommand(sc, rc, ges); if (resp != Response::RespOk) finalResponseCode = resp; } ges.sendToGame(game); return finalResponseCode; }