bool ServerSocketInterface::initSession() { Event_ServerIdentification identEvent; identEvent.set_server_name(servatrice->getServerName().toStdString()); identEvent.set_server_version(VERSION_STRING); identEvent.set_protocol_version(protocolVersion); SessionEvent *identSe = prepareSessionEvent(identEvent); sendProtocolItem(*identSe); delete identSe; int maxUsers = servatrice->getMaxUsersPerAddress(); //allow unlimited number of connections from the trusted sources QString trustedSources = settingsCache->value("server/trusted_sources","127.0.0.1,::1").toString(); if (trustedSources.contains(socket->peerAddress().toString(),Qt::CaseInsensitive)) return true; if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS); SessionEvent *se = prepareSessionEvent(event); sendProtocolItem(*se); delete se; return false; } return true; }
Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message &cmd, ResponseContainer &rc) { if (authState == NotLoggedIn) return Response::RespLoginNeeded; QReadLocker locker(&server->clientsLock); QString receiver = QString::fromStdString(cmd.user_name()); Server_AbstractUserInterface *userInterface = server->findUser(receiver); if (!userInterface) return Response::RespNameNotFound; if (databaseInterface->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) return Response::RespInIgnoreList; Event_UserMessage event; event.set_sender_name(userInfo->name()); event.set_receiver_name(cmd.user_name()); event.set_message(cmd.message()); SessionEvent *se = prepareSessionEvent(event); userInterface->sendProtocolItem(*se); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se); return Response::RespOk; }
bool ServerSocketInterface::initSession() { Event_ServerIdentification identEvent; identEvent.set_server_name(servatrice->getServerName().toStdString()); identEvent.set_server_version(VERSION_STRING); identEvent.set_protocol_version(protocolVersion); SessionEvent *identSe = prepareSessionEvent(identEvent); sendProtocolItem(*identSe); delete identSe; //limit the number of total users based on configuration settings bool enforceUserLimit = settingsCache->value("security/enable_max_user_limit", false).toBool(); if (enforceUserLimit){ int userLimit = settingsCache->value("security/max_users_total", 500).toInt(); int playerCount = (databaseInterface->getActiveUserCount() + 1); if (playerCount > userLimit){ std::cerr << "Max Users Total Limit Reached, please increase the max_users_total setting." << std::endl; logger->logMessage(QString("Max Users Total Limit Reached, please increase the max_users_total setting."), this); Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::USER_LIMIT_REACHED); SessionEvent *se = prepareSessionEvent(event); sendProtocolItem(*se); delete se; return false; } } //allow unlimited number of connections from the trusted sources QString trustedSources = settingsCache->value("security/trusted_sources","127.0.0.1,::1").toString(); if (trustedSources.contains(socket->peerAddress().toString(),Qt::CaseInsensitive)) return true; int maxUsers = servatrice->getMaxUsersPerAddress(); if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS); SessionEvent *se = prepareSessionEvent(event); sendProtocolItem(*se); delete se; return false; } return true; }
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc) { QString userName = QString::fromStdString(cmd.user_name()).simplified(); QString clientId = QString::fromStdString(cmd.clientid()).simplified(); if (userName.isEmpty() || (userInfo != 0)) return Response::RespContextError; QString reasonStr; int banSecondsLeft = 0; AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId); switch (res) { case UserIsBanned: { Response_Login *re = new Response_Login; re->set_denied_reason_str(reasonStr.toStdString()); if (banSecondsLeft != 0) re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toTime_t()); rc.setResponseExtension(re); return Response::RespUserIsBanned; } case NotLoggedIn: return Response::RespWrongPassword; case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession; case UsernameInvalid: { Response_Login *re = new Response_Login; re->set_denied_reason_str(reasonStr.toStdString()); rc.setResponseExtension(re); return Response::RespUsernameInvalid; } case RegistrationRequired: return Response::RespRegistrationRequired; case ClientIdRequired: return Response::RespClientIdRequired; case UserIsInactive: return Response::RespAccountNotActivated; default: authState = res; } userName = QString::fromStdString(userInfo->name()); Event_ServerMessage event; event.set_message(server->getLoginMessage().toStdString()); rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); Response_Login *re = new Response_Login; re->mutable_user_info()->CopyFrom(copyUserInfo(true)); if (authState == PasswordRight) { QMapIterator<QString, ServerInfo_User> buddyIterator(databaseInterface->getBuddyList(userName)); while (buddyIterator.hasNext()) re->add_buddy_list()->CopyFrom(buddyIterator.next().value()); QMapIterator<QString, ServerInfo_User> ignoreIterator(databaseInterface->getIgnoreList(userName)); while (ignoreIterator.hasNext()) re->add_ignore_list()->CopyFrom(ignoreIterator.next().value()); } joinPersistentGames(rc); rc.setResponseExtension(re); return Response::RespOk; }
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; }
void Server_ProtocolHandler::pingClockTimeout() { int cmdcountinterval = server->getCommandCountingInterval(); int msgcountinterval = server->getMessageCountingInterval(); int pingclockinterval = server->getClientKeepAlive(); int interval = server->getMessageCountingInterval(); if (interval > 0) { if(pingclockinterval > 0) { messageSizeOverTime.prepend(0); if (messageSizeOverTime.size() > (msgcountinterval / pingclockinterval)) messageSizeOverTime.removeLast(); messageCountOverTime.prepend(0); if (messageCountOverTime.size() > (msgcountinterval / pingclockinterval)) messageCountOverTime.removeLast(); } } interval = server->getCommandCountingInterval(); if (interval > 0) { if (pingclockinterval > 0) { commandCountOverTime.prepend(0); if (commandCountOverTime.size() > (cmdcountinterval / pingclockinterval)) commandCountOverTime.removeLast(); } } if (timeRunning - lastDataReceived > server->getMaxPlayerInactivityTime()) prepareDestroy(); if (!userInfo || QString::fromStdString(userInfo->privlevel()).toLower() == "none") { if ((server->getIdleClientTimeout() > 0) && (idleClientWarningSent)) { if (timeRunning - lastActionReceived > server->getIdleClientTimeout()) { prepareDestroy(); } } if (((timeRunning - lastActionReceived) >= ceil(server->getIdleClientTimeout() *.9)) && (!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) { Event_NotifyUser event; event.set_type(Event_NotifyUser::IDLEWARNING); SessionEvent *se = prepareSessionEvent(event); sendProtocolItem(*se); delete se; idleClientWarningSent = true; } } ++timeRunning; }
Response::ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc) { if (authState != PasswordRight) return Response::RespFunctionNotAllowed; QString list = QString::fromStdString(cmd.list()); QString user = QString::fromStdString(cmd.user_name()); if ((list != "buddy") && (list != "ignore")) return Response::RespContextError; if (list == "buddy") if (databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) return Response::RespContextError; if (list == "ignore") if (databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) return Response::RespContextError; int id1 = userInfo->id(); int id2 = sqlInterface->getUserIdInDB(user); if (id2 < 0) return Response::RespNameNotFound; if (id1 == id2) return Response::RespContextError; QSqlQuery query(sqlInterface->getDatabase()); query.prepare("insert into " + servatrice->getDbPrefix() + "_" + list + "list (id_user1, id_user2) values(:id1, :id2)"); query.bindValue(":id1", id1); query.bindValue(":id2", id2); if (!sqlInterface->execSqlQuery(query)) return Response::RespInternalError; Event_AddToList event; event.set_list_name(cmd.list()); event.mutable_user_info()->CopyFrom(databaseInterface->getUserData(user)); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); return Response::RespOk; }
Response::ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc) { if (authState != PasswordRight) return Response::RespFunctionNotAllowed; QString list = QString::fromStdString(cmd.list()); QString user = QString::fromStdString(cmd.user_name()); if ((list != "buddy") && (list != "ignore")) return Response::RespContextError; if (list == "buddy") if (!databaseInterface->isInBuddyList(QString::fromStdString(userInfo->name()), user)) return Response::RespContextError; if (list == "ignore") if (!databaseInterface->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) return Response::RespContextError; int id1 = userInfo->id(); int id2 = sqlInterface->getUserIdInDB(user); if (id2 < 0) return Response::RespNameNotFound; QSqlQuery *query = sqlInterface->prepareQuery("delete from {prefix}_" + list + "list where id_user1 = :id1 and id_user2 = :id2"); query->bindValue(":id1", id1); query->bindValue(":id2", id2); if (!sqlInterface->execSqlQuery(query)) return Response::RespInternalError; Event_RemoveFromList event; event.set_list_name(cmd.list()); event.set_user_name(cmd.user_name()); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); return Response::RespOk; }
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc) { QString userName = QString::fromStdString(cmd.user_name()).simplified(); QString clientId = QString::fromStdString(cmd.clientid()).simplified(); QString clientVersion = QString::fromStdString(cmd.clientver()).simplified(); if (userName.isEmpty() || (userInfo != 0)) return Response::RespContextError; // check client feature set against server feature set FeatureSet features; QMap<QString, bool> receivedClientFeatures; QMap<QString, bool> missingClientFeatures; for (int i = 0; i < cmd.clientfeatures().size(); ++i) receivedClientFeatures.insert(QString::fromStdString(cmd.clientfeatures(i)).simplified(), false); missingClientFeatures = features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList()); if (!missingClientFeatures.isEmpty()) { if (features.isRequiredFeaturesMissing(missingClientFeatures, server->getServerRequiredFeatureList())) { Response_Login *re = new Response_Login; re->set_denied_reason_str("Client upgrade required"); QMap<QString, bool>::iterator i; for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i) re->add_missing_features(i.key().toStdString().c_str()); rc.setResponseExtension(re); return Response::RespClientUpdateRequired; } } QString reasonStr; int banSecondsLeft = 0; AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId, clientVersion); switch (res) { case UserIsBanned: { Response_Login *re = new Response_Login; re->set_denied_reason_str(reasonStr.toStdString()); if (banSecondsLeft != 0) re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toTime_t()); rc.setResponseExtension(re); return Response::RespUserIsBanned; } case NotLoggedIn: return Response::RespWrongPassword; case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession; case UsernameInvalid: { Response_Login *re = new Response_Login; re->set_denied_reason_str(reasonStr.toStdString()); rc.setResponseExtension(re); return Response::RespUsernameInvalid; } case RegistrationRequired: return Response::RespRegistrationRequired; case ClientIdRequired: return Response::RespClientIdRequired; case UserIsInactive: return Response::RespAccountNotActivated; default: authState = res; } userName = QString::fromStdString(userInfo->name()); Event_ServerMessage event; event.set_message(server->getLoginMessage().toStdString()); rc.enqueuePostResponseItem(ServerMessage::SESSION_EVENT, prepareSessionEvent(event)); Response_Login *re = new Response_Login; re->mutable_user_info()->CopyFrom(copyUserInfo(true)); if (authState == PasswordRight) { QMapIterator<QString, ServerInfo_User> buddyIterator(databaseInterface->getBuddyList(userName)); while (buddyIterator.hasNext()) re->add_buddy_list()->CopyFrom(buddyIterator.next().value()); QMapIterator<QString, ServerInfo_User> ignoreIterator(databaseInterface->getIgnoreList(userName)); while (ignoreIterator.hasNext()) re->add_ignore_list()->CopyFrom(ignoreIterator.next().value()); } // return to client any missing features the server has that the client does not if (!missingClientFeatures.isEmpty()) { QMap<QString, bool>::iterator i; for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i) re->add_missing_features(i.key().toStdString().c_str()); } joinPersistentGames(rc); rc.setResponseExtension(re); return Response::RespOk; }