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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 9
0
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;
}