parent
e9a81cd185
commit
6097f0b389
|
@ -36,7 +36,7 @@ local function tellRoomToObserver(self, player)
|
||||||
player:doNotify("UpdateDrawPile", #self.draw_pile)
|
player:doNotify("UpdateDrawPile", #self.draw_pile)
|
||||||
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
|
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
|
||||||
|
|
||||||
table.insert(self.observers, {observee.id, player})
|
table.insert(self.observers, {observee.id, player, player:getId()})
|
||||||
end
|
end
|
||||||
|
|
||||||
local function addObserver(self, id)
|
local function addObserver(self, id)
|
||||||
|
@ -56,12 +56,10 @@ end
|
||||||
|
|
||||||
local function removeObserver(self, id)
|
local function removeObserver(self, id)
|
||||||
for _, t in ipairs(self.observers) do
|
for _, t in ipairs(self.observers) do
|
||||||
local __, p = table.unpack(t)
|
local pid = t[3]
|
||||||
if p:getId() == id then
|
if pid == id then
|
||||||
table.removeOne(self.observers, t)
|
table.removeOne(self.observers, t)
|
||||||
self:doBroadcastNotify("RemoveObserver", json.encode{
|
self:doBroadcastNotify("RemoveObserver", json.encode{ pid })
|
||||||
p:getId(),
|
|
||||||
})
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,7 +47,7 @@ function ServerPlayer:doNotify(command, jsonData)
|
||||||
local room = self.room
|
local room = self.room
|
||||||
for _, t in ipairs(room.observers) do
|
for _, t in ipairs(room.observers) do
|
||||||
local id, p = table.unpack(t)
|
local id, p = table.unpack(t)
|
||||||
if id == self.id then
|
if id == self.id and room.room:hasObserver(p) then
|
||||||
p:doNotify(command, jsonData)
|
p:doNotify(command, jsonData)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,15 @@ CREATE TABLE IF NOT EXISTS banip (
|
||||||
ip VARCHAR(64)
|
ip VARCHAR(64)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS uuidinfo (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
uuid VARCHAR(32)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS banuuid (
|
||||||
|
uuid VARCHAR(32)
|
||||||
|
);
|
||||||
|
|
||||||
-- 胜率相关
|
-- 胜率相关
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS winRate (
|
CREATE TABLE IF NOT EXISTS winRate (
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <qcryptographichash.h>
|
#include <qcryptographichash.h>
|
||||||
#include <qnamespace.h>
|
#include <qnamespace.h>
|
||||||
#include <qregularexpression.h>
|
#include <qregularexpression.h>
|
||||||
|
#include <QSysInfo>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int luaopen_fk(lua_State *);
|
int luaopen_fk(lua_State *);
|
||||||
|
@ -203,6 +204,10 @@ QJsonDocument String2Json(const QString &str) {
|
||||||
return QJsonDocument::fromJson(bytes);
|
return QJsonDocument::fromJson(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GetDeviceUuid() {
|
||||||
|
return QSysInfo::machineUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
QString Color(const QString &raw, fkShell::TextColor color,
|
QString Color(const QString &raw, fkShell::TextColor color,
|
||||||
fkShell::TextType type) {
|
fkShell::TextType type) {
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
|
|
@ -20,6 +20,8 @@ QString calcFileMD5();
|
||||||
QByteArray JsonArray2Bytes(const QJsonArray &arr);
|
QByteArray JsonArray2Bytes(const QJsonArray &arr);
|
||||||
QJsonDocument String2Json(const QString &str);
|
QJsonDocument String2Json(const QString &str);
|
||||||
|
|
||||||
|
QString GetDeviceUuid();
|
||||||
|
|
||||||
namespace fkShell {
|
namespace fkShell {
|
||||||
enum TextColor {
|
enum TextColor {
|
||||||
Black,
|
Black,
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
#include <qjsonarray.h>
|
#include <qjsonarray.h>
|
||||||
#include <qjsondocument.h>
|
#include <qjsondocument.h>
|
||||||
|
|
||||||
|
#ifdef FK_SERVER_ONLY
|
||||||
|
static void *ClientInstance = nullptr;
|
||||||
|
#else
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "client_socket.h"
|
#include "client_socket.h"
|
||||||
#include "roomthread.h"
|
#include "roomthread.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
@ -268,15 +273,15 @@ void Room::removePlayer(ServerPlayer *player) {
|
||||||
// 原先的跑路机器人会在游戏结束后自动销毁掉
|
// 原先的跑路机器人会在游戏结束后自动销毁掉
|
||||||
server->addPlayer(runner);
|
server->addPlayer(runner);
|
||||||
|
|
||||||
// 如果走小道的人不是单机启动玩家 那么直接ban
|
|
||||||
if (!ClientInstance && !player->isDied()) {
|
|
||||||
server->temporarilyBan(runner->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_thread->wakeUp();
|
m_thread->wakeUp();
|
||||||
|
|
||||||
// 发出信号,让大厅添加这个人
|
// 发出信号,让大厅添加这个人
|
||||||
emit playerRemoved(runner);
|
emit playerRemoved(runner);
|
||||||
|
|
||||||
|
// 如果走小道的人不是单机启动玩家 那么直接ban
|
||||||
|
if (!ClientInstance && !player->isDied()) {
|
||||||
|
server->temporarilyBan(runner->getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果房间空了,就把房间标为废弃,Server有信号处理函数的
|
// 如果房间空了,就把房间标为废弃,Server有信号处理函数的
|
||||||
|
@ -341,6 +346,8 @@ void Room::removeObserver(ServerPlayer *player) {
|
||||||
|
|
||||||
QList<ServerPlayer *> Room::getObservers() const { return observers; }
|
QList<ServerPlayer *> Room::getObservers() const { return observers; }
|
||||||
|
|
||||||
|
bool Room::hasObserver(ServerPlayer *player) const { return observers.contains(player); }
|
||||||
|
|
||||||
int Room::getTimeout() const { return timeout; }
|
int Room::getTimeout() const { return timeout; }
|
||||||
|
|
||||||
void Room::setTimeout(int timeout) { this->timeout = timeout; }
|
void Room::setTimeout(int timeout) { this->timeout = timeout; }
|
||||||
|
|
|
@ -45,6 +45,7 @@ class Room : public QObject {
|
||||||
void addObserver(ServerPlayer *player);
|
void addObserver(ServerPlayer *player);
|
||||||
void removeObserver(ServerPlayer *player);
|
void removeObserver(ServerPlayer *player);
|
||||||
QList<ServerPlayer *> getObservers() const;
|
QList<ServerPlayer *> getObservers() const;
|
||||||
|
bool hasObserver(ServerPlayer *player) const;
|
||||||
|
|
||||||
int getTimeout() const;
|
int getTimeout() const;
|
||||||
void setTimeout(int timeout);
|
void setTimeout(int timeout);
|
||||||
|
|
|
@ -273,7 +273,7 @@ void Server::processRequest(const QByteArray &msg) {
|
||||||
doc[2] != "Setup")
|
doc[2] != "Setup")
|
||||||
valid = false;
|
valid = false;
|
||||||
else
|
else
|
||||||
valid = (String2Json(doc[3].toString()).array().size() == 4);
|
valid = (String2Json(doc[3].toString()).array().size() == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
@ -313,13 +313,34 @@ void Server::processRequest(const QByteArray &msg) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto uuid = arr[4].toString();
|
||||||
|
auto result2 = QJsonArray({1});
|
||||||
|
if (CheckSqlString(uuid)) {
|
||||||
|
result2 = SelectFromDatabase(
|
||||||
|
db, QString("SELECT * FROM banuuid WHERE uuid='%1';").arg(uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result2.isEmpty()) {
|
||||||
|
QJsonArray body;
|
||||||
|
body << -2;
|
||||||
|
body << (Router::TYPE_NOTIFICATION | Router::SRC_SERVER |
|
||||||
|
Router::DEST_CLIENT);
|
||||||
|
body << "ErrorMsg";
|
||||||
|
body << "you have been banned!";
|
||||||
|
client->send(JsonArray2Bytes(body));
|
||||||
|
qInfo() << "Refused banned UUID:" << uuid;
|
||||||
|
client->disconnectFromHost();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
handleNameAndPassword(client, arr[0].toString(), arr[1].toString(),
|
handleNameAndPassword(client, arr[0].toString(), arr[1].toString(),
|
||||||
arr[2].toString());
|
arr[2].toString(), uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
|
void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
const QString &md5_str) {
|
const QString &md5_str,
|
||||||
|
const QString &uuid_str) {
|
||||||
auto encryted_pw = QByteArray::fromBase64(password.toLatin1());
|
auto encryted_pw = QByteArray::fromBase64(password.toLatin1());
|
||||||
unsigned char buf[4096] = {0};
|
unsigned char buf[4096] = {0};
|
||||||
RSA_private_decrypt(RSA_size(rsa), (const unsigned char *)encryted_pw.data(),
|
RSA_private_decrypt(RSA_size(rsa), (const unsigned char *)encryted_pw.data(),
|
||||||
|
@ -462,6 +483,9 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
|
||||||
.arg(obj["id"].toString().toInt());
|
.arg(obj["id"].toString().toInt());
|
||||||
ExecSQL(db, sql_update);
|
ExecSQL(db, sql_update);
|
||||||
|
|
||||||
|
auto uuid_update = QString("REPLACE INTO uuidinfo (id, uuid) VALUES (%1, '%2');").arg(obj["id"].toString().toInt()).arg(uuid_str);
|
||||||
|
ExecSQL(db, uuid_update);
|
||||||
|
|
||||||
// create new ServerPlayer and setup
|
// create new ServerPlayer and setup
|
||||||
ServerPlayer *player = new ServerPlayer(lobby());
|
ServerPlayer *player = new ServerPlayer(lobby());
|
||||||
player->setSocket(client);
|
player->setSocket(client);
|
||||||
|
|
|
@ -86,7 +86,7 @@ private:
|
||||||
void readConfig();
|
void readConfig();
|
||||||
|
|
||||||
void handleNameAndPassword(ClientSocket *client, const QString &name,
|
void handleNameAndPassword(ClientSocket *client, const QString &name,
|
||||||
const QString &password, const QString &md5_str);
|
const QString &password, const QString &md5_str, const QString &uuid_str);
|
||||||
void processDatagram(const QByteArray &msg, const QHostAddress &addr, uint port);
|
void processDatagram(const QByteArray &msg, const QHostAddress &addr, uint port);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,16 +29,24 @@ void Shell::helpCommand(QStringList &) {
|
||||||
HELP_MSG("%s: List all running rooms.", "lsroom");
|
HELP_MSG("%s: List all running rooms.", "lsroom");
|
||||||
HELP_MSG("%s: Kick a player by his <id>.", "kick");
|
HELP_MSG("%s: Kick a player by his <id>.", "kick");
|
||||||
HELP_MSG("%s: Broadcast message.", "msg");
|
HELP_MSG("%s: Broadcast message.", "msg");
|
||||||
HELP_MSG("%s: Ban 1 or more accounts by their <name>.", "ban");
|
HELP_MSG("%s: Ban 1 or more accounts, IP, UUID by their <name>.", "ban");
|
||||||
HELP_MSG("%s: Unban 1 or more accounts by their <name>.", "unban");
|
HELP_MSG("%s: Unban 1 or more accounts by their <name>.", "unban");
|
||||||
HELP_MSG(
|
HELP_MSG(
|
||||||
"%s: Ban 1 or more IP address according to somebody's 'lastLoginIp'. "
|
"%s: Ban 1 or more IP address. "
|
||||||
"At least 1 <name> required.",
|
"At least 1 <name> required.",
|
||||||
"banip");
|
"banip");
|
||||||
HELP_MSG(
|
HELP_MSG(
|
||||||
"%s: Unban 1 or more IP address according to somebody's 'lastLoginIp'. "
|
"%s: Unban 1 or more IP address. "
|
||||||
"At least 1 <name> required.",
|
"At least 1 <name> required.",
|
||||||
"unbanip");
|
"unbanip");
|
||||||
|
HELP_MSG(
|
||||||
|
"%s: Ban 1 or more UUID. "
|
||||||
|
"At least 1 <name> required.",
|
||||||
|
"banuuid");
|
||||||
|
HELP_MSG(
|
||||||
|
"%s: Unban 1 or more UUID. "
|
||||||
|
"At least 1 <name> required.",
|
||||||
|
"unbanuuid");
|
||||||
qInfo();
|
qInfo();
|
||||||
qInfo("===== Package commands =====");
|
qInfo("===== Package commands =====");
|
||||||
HELP_MSG("%s: Install a new package from <url>.", "install");
|
HELP_MSG("%s: Install a new package from <url>.", "install");
|
||||||
|
@ -207,6 +215,9 @@ void Shell::banCommand(QStringList &list) {
|
||||||
foreach (auto name, list) {
|
foreach (auto name, list) {
|
||||||
banAccount(db, name, true);
|
banAccount(db, name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
banipCommand(list);
|
||||||
|
banUuidCommand(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::unbanCommand(QStringList &list) {
|
void Shell::unbanCommand(QStringList &list) {
|
||||||
|
@ -220,7 +231,11 @@ void Shell::unbanCommand(QStringList &list) {
|
||||||
foreach (auto name, list) {
|
foreach (auto name, list) {
|
||||||
banAccount(db, name, false);
|
banAccount(db, name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unbanipCommand(list);
|
||||||
|
unbanUuidCommand(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void banIPByName(sqlite3 *db, const QString &name, bool banned) {
|
static void banIPByName(sqlite3 *db, const QString &name, bool banned) {
|
||||||
if (!CheckSqlString(name))
|
if (!CheckSqlString(name))
|
||||||
return;
|
return;
|
||||||
|
@ -275,6 +290,65 @@ void Shell::unbanipCommand(QStringList &list) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void banUuidByName(sqlite3 *db, const QString &name, bool banned) {
|
||||||
|
if (!CheckSqlString(name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString sql_find = QString("SELECT * FROM userinfo \
|
||||||
|
WHERE name='%1';")
|
||||||
|
.arg(name);
|
||||||
|
auto result = SelectFromDatabase(db, sql_find);
|
||||||
|
if (result.isEmpty())
|
||||||
|
return;
|
||||||
|
auto obj = result[0].toObject();
|
||||||
|
int id = obj["id"].toString().toInt();
|
||||||
|
|
||||||
|
auto result2 = SelectFromDatabase(db, QString("SELECT * FROM uuidinfo WHERE id=%1;").arg(id));
|
||||||
|
if (result2.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto uuid = result2[0].toObject()["uuid"].toString();
|
||||||
|
|
||||||
|
if (banned) {
|
||||||
|
ExecSQL(db, QString("INSERT INTO banuuid VALUES('%1');").arg(uuid));
|
||||||
|
|
||||||
|
auto p = ServerInstance->findPlayer(id);
|
||||||
|
if (p) {
|
||||||
|
p->kicked();
|
||||||
|
}
|
||||||
|
qInfo("Banned UUID %s.", uuid.toUtf8().constData());
|
||||||
|
} else {
|
||||||
|
ExecSQL(db, QString("DELETE FROM banuuid WHERE uuid='%1';").arg(uuid));
|
||||||
|
qInfo("Unbanned UUID %s.", uuid.toUtf8().constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::banUuidCommand(QStringList &list) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
qWarning("The 'banuuid' command needs at least 1 <name>.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto db = ServerInstance->getDatabase();
|
||||||
|
|
||||||
|
foreach (auto name, list) {
|
||||||
|
banUuidByName(db, name, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shell::unbanUuidCommand(QStringList &list) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
qWarning("The 'unbanuuid' command needs at least 1 <name>.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto db = ServerInstance->getDatabase();
|
||||||
|
|
||||||
|
foreach (auto name, list) {
|
||||||
|
banUuidByName(db, name, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Shell::Shell() {
|
Shell::Shell() {
|
||||||
setObjectName("Shell");
|
setObjectName("Shell");
|
||||||
signal(SIGINT, sigintHandler);
|
signal(SIGINT, sigintHandler);
|
||||||
|
@ -297,6 +371,8 @@ Shell::Shell() {
|
||||||
handlers["unban"] = &Shell::unbanCommand;
|
handlers["unban"] = &Shell::unbanCommand;
|
||||||
handlers["banip"] = &Shell::banipCommand;
|
handlers["banip"] = &Shell::banipCommand;
|
||||||
handlers["unbanip"] = &Shell::unbanipCommand;
|
handlers["unbanip"] = &Shell::unbanipCommand;
|
||||||
|
handlers["banuuid"] = &Shell::banUuidCommand;
|
||||||
|
handlers["unbanuuid"] = &Shell::unbanUuidCommand;
|
||||||
}
|
}
|
||||||
handler_map = handlers;
|
handler_map = handlers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,10 @@ private:
|
||||||
void msgCommand(QStringList &);
|
void msgCommand(QStringList &);
|
||||||
void banCommand(QStringList &);
|
void banCommand(QStringList &);
|
||||||
void banipCommand(QStringList &);
|
void banipCommand(QStringList &);
|
||||||
|
void banUuidCommand(QStringList &);
|
||||||
void unbanCommand(QStringList &);
|
void unbanCommand(QStringList &);
|
||||||
void unbanipCommand(QStringList &);
|
void unbanipCommand(QStringList &);
|
||||||
|
void unbanUuidCommand(QStringList &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@ public:
|
||||||
QList<ServerPlayer *> getPlayers() const;
|
QList<ServerPlayer *> getPlayers() const;
|
||||||
|
|
||||||
QList<ServerPlayer *> getObservers() const;
|
QList<ServerPlayer *> getObservers() const;
|
||||||
|
bool hasObserver(ServerPlayer *player) const;
|
||||||
int getTimeout() const;
|
int getTimeout() const;
|
||||||
void checkAbandoned();
|
void checkAbandoned();
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,7 @@ void QmlBackend::replyDelayTest(const QString &screenName,
|
||||||
auto md5 = calcFileMD5();
|
auto md5 = calcFileMD5();
|
||||||
|
|
||||||
QJsonArray arr;
|
QJsonArray arr;
|
||||||
arr << screenName << cipher << md5 << FK_VERSION;
|
arr << screenName << cipher << md5 << FK_VERSION << GetDeviceUuid();
|
||||||
ClientInstance->notifyServer("Setup", JsonArray2Bytes(arr));
|
ClientInstance->notifyServer("Setup", JsonArray2Bytes(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue