mirror of
https://github.com/QuasarApp/Hanoi-Towers.git
synced 2025-04-27 02:04:32 +00:00
229 lines
6.4 KiB
C++
229 lines
6.4 KiB
C++
/*
|
|
* Copyright (C) 2018-2021 QuasarApp.
|
|
* Distributed under the lgplv3 software license, see the accompanying
|
|
* Everyone is permitted to copy and distribute verbatim copies
|
|
* of this license document, but changing it is not allowed.
|
|
*/
|
|
|
|
#include "hanoiserver.h"
|
|
#include <QDir>
|
|
#include <QNetworkInterface>
|
|
#include <QCoreApplication>
|
|
#include <userdata.h>
|
|
#include <usermember.h>
|
|
#include <userdatarequest.h>
|
|
#include <basenodeinfo.h>
|
|
#include <world.h>
|
|
#include "config.h"
|
|
#include "basedefines.h"
|
|
#include "badrequest.h"
|
|
#include "hanoierrorcodes.h"
|
|
#include <fixworldrequest.h>
|
|
#include <worldupdate.h>
|
|
#include <isqldbcache.h>
|
|
|
|
HanoiServer::HanoiServer() {
|
|
QString address = "";
|
|
unsigned short port = DEFAULT_HANOI_PORT;
|
|
|
|
if (QuasarAppUtils::Params::isEndable("address")) {
|
|
auto addressList = QuasarAppUtils::Params::getStrArg("address").split(":");
|
|
if (address.size() != 2) {
|
|
|
|
QuasarAppUtils::Params::log("invalid address params",
|
|
QuasarAppUtils::Error);
|
|
QCoreApplication ::exit(2);
|
|
|
|
}
|
|
|
|
address = addressList.first();
|
|
port = static_cast<decltype (port)>(addressList.last().toInt());
|
|
}
|
|
|
|
if (!run(address, port)) {
|
|
QuasarAppUtils::Params::log("fail to run server",
|
|
QuasarAppUtils::Error);
|
|
QCoreApplication ::exit(3);
|
|
|
|
}
|
|
|
|
registerPackageType<UserData>();
|
|
registerPackageType<UserDataRequest>();
|
|
registerPackageType<FixWorldRequest>();
|
|
registerPackageType<World>();
|
|
registerPackageType<WorldUpdate>();
|
|
|
|
|
|
}
|
|
|
|
HanoiServer::~HanoiServer() {
|
|
}
|
|
|
|
QH::ParserResult HanoiServer::parsePackage(const QSharedPointer<QH::PKG::AbstractData> &pkg,
|
|
const QH::Header &pkgHeader,
|
|
const QH::AbstractNodeInfo *sender) {
|
|
|
|
auto parentResult = SingleServer::parsePackage(pkg, pkgHeader, sender);
|
|
if (parentResult != QH::ParserResult::NotProcessed) {
|
|
return parentResult;
|
|
}
|
|
|
|
if (H_16<UserData>() == pkg->cmd()) {
|
|
auto obj = pkg.staticCast<UserData>();
|
|
|
|
auto requesterId = getSender(sender, obj.data());
|
|
|
|
auto opResult = updateIfNotExistsCreateObject(requesterId, obj);
|
|
if (opResult != QH::DBOperationResult::Allowed) {
|
|
return QH::ParserResult::Error;
|
|
}
|
|
|
|
updateUserInWorld(obj.data());
|
|
|
|
return QH::ParserResult::Processed;
|
|
|
|
} else if (H_16<UserDataRequest>() == pkg->cmd()) {
|
|
auto obj = pkg.staticCast<UserDataRequest>();
|
|
|
|
if (!workWirthUserData(obj.data(), sender, &pkgHeader)) {
|
|
return QH::ParserResult::Error;
|
|
}
|
|
|
|
return QH::ParserResult::Processed;
|
|
|
|
} else if (H_16<FixWorldRequest>() == pkg->cmd()) {
|
|
unsigned int version = (static_cast<FixWorldRequest*>(pkg.data()))->worldVersion();
|
|
|
|
for (unsigned int i = version; i <= _world->getWorldVersion(); ++i) {
|
|
auto point = getHistoryPoint(i);
|
|
sendData(point.data(), sender->networkAddress(), &pkgHeader);
|
|
}
|
|
}
|
|
|
|
return QH::ParserResult::NotProcessed;
|
|
}
|
|
|
|
QStringList HanoiServer::SQLSources() const {
|
|
return SingleServer::SQLSources() << ":/HanoiTowersSql/sql/database.sql";
|
|
}
|
|
|
|
QVariantMap HanoiServer::defaultDbParams() const {
|
|
return QH::DataBaseNode::defaultDbParams();
|
|
}
|
|
|
|
bool HanoiServer::workWirthUserData(const UserData *obj,
|
|
const QH::AbstractNodeInfo *sender,
|
|
const QH::Header *oldHeader) {
|
|
|
|
QSharedPointer<DBObject> userData;
|
|
|
|
if (getObject(getSender(sender, obj), *obj, userData) != QH::DBOperationResult::Allowed) {
|
|
if (oldHeader) {
|
|
badRequest(sender->networkAddress(), *oldHeader,
|
|
{
|
|
ErrorCodes::PermissionDenied,
|
|
"The user don not have a premsion of the requested object."
|
|
});
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return sendData(userData.data(), sender->networkAddress(), oldHeader);
|
|
}
|
|
|
|
void HanoiServer::updateUserInWorld(const UserData *data) {
|
|
UserPreview user;
|
|
user.id = data->getId().toString();
|
|
user.record = data->userData()._record;
|
|
user.userName = data->name();
|
|
|
|
updateWorld(user, false);
|
|
}
|
|
|
|
void HanoiServer::removeUserFromWorld(const QString &userId) {
|
|
UserPreview user;
|
|
user.id = userId;
|
|
|
|
updateWorld(user, true);
|
|
}
|
|
|
|
void HanoiServer::updateWorld(const UserPreview &user, bool isRemove) {
|
|
auto update = QSharedPointer<WorldUpdate>::create();
|
|
update->setWorldVersion(_world->getWorldVersion() + 1);
|
|
|
|
if (isRemove)
|
|
update->setDataRemove({user.id});
|
|
else
|
|
update->setDataAddUpdate({{user.id, user}});
|
|
|
|
_worldHistory[update->getWorldVersion()] = update;
|
|
|
|
_world->applyUpdate(*update.data());
|
|
|
|
objectChanged(update);
|
|
}
|
|
|
|
QSharedPointer<WorldUpdate>
|
|
HanoiServer::getHistoryPoint(unsigned int version) {
|
|
QMutexLocker lock(&_worldHistoryMutexl);
|
|
return _worldHistory[version];
|
|
}
|
|
|
|
bool HanoiServer::initWorld() {
|
|
if (!db()) {
|
|
return false;
|
|
}
|
|
|
|
_world = db()->getObject(World{});
|
|
|
|
return _world && _world->isValid();
|
|
}
|
|
|
|
void HanoiServer::nodeConfirmend(QH::AbstractNodeInfo *node) {
|
|
if (auto baseNode = dynamic_cast<QH::BaseNodeInfo*>(node)) {
|
|
UserDataRequest request;
|
|
|
|
request.setId(baseNode->id());
|
|
|
|
workWirthUserData(&request, node);
|
|
|
|
}
|
|
}
|
|
|
|
QH::ErrorCodes::Code HanoiServer::deleteUser(const QSharedPointer<UserMember> &user,
|
|
const QH::AbstractNodeInfo *info) {
|
|
|
|
QH::ErrorCodes::Code code = QH::SingleServer::deleteUser(user, info);
|
|
if (code == QH::ErrorCodes::NoError) {
|
|
|
|
auto baseNode = dynamic_cast<const QH::BaseNodeInfo*>(info);
|
|
if (baseNode) {
|
|
removeUserFromWorld(baseNode->id().toString());
|
|
}
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
void HanoiServer::memberSubsribed(const QVariant &clientId,
|
|
unsigned int subscribeId) {
|
|
|
|
if (subscribeId == _world->subscribeId()) {
|
|
sendData(_world.data(), clientId);
|
|
}
|
|
}
|
|
|
|
bool HanoiServer::initSqlDb(QString DBparamsFile,
|
|
QH::ISqlDBCache *cache,
|
|
QH::SqlDBWriter *writer) {
|
|
|
|
if (!SingleServer::initSqlDb(DBparamsFile, cache, writer)) {
|
|
return false;
|
|
}
|
|
|
|
return initWorld();
|
|
|
|
}
|
|
|