2022-01-24 02:23:08 +00:00
|
|
|
#include "router.h"
|
|
|
|
#include "client.h"
|
2022-03-27 06:49:41 +00:00
|
|
|
#include "client_socket.h"
|
2022-01-24 02:23:08 +00:00
|
|
|
#include "server.h"
|
2022-03-01 05:18:00 +00:00
|
|
|
#include "serverplayer.h"
|
2022-01-24 02:23:08 +00:00
|
|
|
|
|
|
|
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
this->type = type;
|
|
|
|
this->socket = nullptr;
|
|
|
|
setSocket(socket);
|
|
|
|
expectedReplyId = -1;
|
|
|
|
replyTimeout = 0;
|
|
|
|
extraReplyReadySemaphore = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Router::~Router()
|
|
|
|
{
|
|
|
|
abortRequest();
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientSocket* Router::getSocket() const
|
|
|
|
{
|
|
|
|
return socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Router::setSocket(ClientSocket *socket)
|
|
|
|
{
|
|
|
|
if (this->socket != nullptr) {
|
|
|
|
this->socket->disconnect(this);
|
|
|
|
disconnect(this->socket);
|
|
|
|
this->socket->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
this->socket = nullptr;
|
|
|
|
if (socket != nullptr) {
|
|
|
|
connect(this, &Router::messageReady, socket, &ClientSocket::send);
|
|
|
|
connect(socket, &ClientSocket::message_got, this, &Router::handlePacket);
|
|
|
|
connect(socket, &ClientSocket::disconnected, this, &Router::abortRequest);
|
|
|
|
socket->setParent(this);
|
|
|
|
this->socket = socket;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Router::setReplyReadySemaphore(QSemaphore *semaphore)
|
|
|
|
{
|
|
|
|
extraReplyReadySemaphore = semaphore;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Router::request(int type, const QString& command,
|
2022-03-02 12:56:37 +00:00
|
|
|
const QString& jsonData, int timeout)
|
2022-01-24 02:23:08 +00:00
|
|
|
{
|
|
|
|
// In case a request is called without a following waitForReply call
|
|
|
|
if (replyReadySemaphore.available() > 0)
|
|
|
|
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
|
|
|
|
|
|
|
static int requestId = 0;
|
|
|
|
requestId++;
|
|
|
|
|
|
|
|
replyMutex.lock();
|
|
|
|
expectedReplyId = requestId;
|
2022-03-30 06:14:40 +00:00
|
|
|
replyTimeout = timeout;
|
2022-01-24 02:23:08 +00:00
|
|
|
requestStartTime = QDateTime::currentDateTime();
|
|
|
|
m_reply = QString();
|
|
|
|
replyMutex.unlock();
|
|
|
|
|
|
|
|
QJsonArray body;
|
|
|
|
body << requestId;
|
|
|
|
body << type;
|
|
|
|
body << command;
|
2022-03-02 12:56:37 +00:00
|
|
|
body << jsonData;
|
2022-01-24 02:23:08 +00:00
|
|
|
body << timeout;
|
|
|
|
|
|
|
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
|
|
|
}
|
|
|
|
|
2022-03-02 12:56:37 +00:00
|
|
|
void Router::reply(int type, const QString& command, const QString& jsonData)
|
2022-01-24 02:23:08 +00:00
|
|
|
{
|
|
|
|
QJsonArray body;
|
|
|
|
body << this->requestId;
|
|
|
|
body << type;
|
|
|
|
body << command;
|
2022-03-02 12:56:37 +00:00
|
|
|
body << jsonData;
|
2022-01-24 02:23:08 +00:00
|
|
|
|
|
|
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
|
|
|
}
|
|
|
|
|
2022-03-02 12:56:37 +00:00
|
|
|
void Router::notify(int type, const QString& command, const QString& jsonData)
|
2022-01-24 02:23:08 +00:00
|
|
|
{
|
|
|
|
QJsonArray body;
|
|
|
|
body << -2; // requestId = -2 mean this is for notification
|
|
|
|
body << type;
|
|
|
|
body << command;
|
2022-03-02 12:56:37 +00:00
|
|
|
body << jsonData;
|
2022-01-24 02:23:08 +00:00
|
|
|
|
|
|
|
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
|
|
|
}
|
|
|
|
|
|
|
|
int Router::getTimeout() const
|
|
|
|
{
|
|
|
|
return requestTimeout;
|
|
|
|
}
|
|
|
|
|
|
|
|
// cancel last request from the sender
|
|
|
|
void Router::cancelRequest()
|
|
|
|
{
|
|
|
|
replyMutex.lock();
|
|
|
|
expectedReplyId = -1;
|
|
|
|
replyTimeout = 0;
|
|
|
|
extraReplyReadySemaphore = nullptr;
|
|
|
|
replyMutex.unlock();
|
|
|
|
|
|
|
|
if (replyReadySemaphore.available() > 0)
|
|
|
|
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Router::waitForReply()
|
|
|
|
{
|
|
|
|
replyReadySemaphore.acquire();
|
|
|
|
return m_reply;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Router::waitForReply(int timeout)
|
|
|
|
{
|
2022-03-30 06:14:40 +00:00
|
|
|
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
2022-01-24 02:23:08 +00:00
|
|
|
return m_reply;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Router::abortRequest()
|
|
|
|
{
|
|
|
|
replyMutex.lock();
|
|
|
|
if (expectedReplyId != -1) {
|
|
|
|
replyReadySemaphore.release();
|
|
|
|
if (extraReplyReadySemaphore)
|
|
|
|
extraReplyReadySemaphore->release();
|
|
|
|
expectedReplyId = -1;
|
|
|
|
extraReplyReadySemaphore = nullptr;
|
|
|
|
}
|
|
|
|
replyMutex.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Router::handlePacket(const QByteArray& rawPacket)
|
|
|
|
{
|
|
|
|
QJsonDocument packet = QJsonDocument::fromJson(rawPacket);
|
|
|
|
if (packet.isNull() || !packet.isArray())
|
|
|
|
return;
|
|
|
|
|
|
|
|
int requestId = packet[0].toInt();
|
|
|
|
int type = packet[1].toInt();
|
|
|
|
QString command = packet[2].toString();
|
2022-03-02 12:56:37 +00:00
|
|
|
QString jsonData = packet[3].toString();
|
2022-01-24 02:23:08 +00:00
|
|
|
|
|
|
|
if (type & TYPE_NOTIFICATION) {
|
|
|
|
if (type & DEST_CLIENT) {
|
2022-03-02 12:56:37 +00:00
|
|
|
ClientInstance->callLua(command, jsonData);
|
2022-01-24 02:23:08 +00:00
|
|
|
} else {
|
2022-04-01 12:51:01 +00:00
|
|
|
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
2022-03-02 12:56:37 +00:00
|
|
|
// Add the uid of sender to jsonData
|
|
|
|
QJsonArray arr = QJsonDocument::fromJson(jsonData.toUtf8()).array();
|
2022-04-01 12:51:01 +00:00
|
|
|
arr.prepend(player->getId());
|
2022-04-03 13:43:35 +00:00
|
|
|
|
|
|
|
Room *room = player->getRoom();
|
|
|
|
room->lockLua(__FUNCTION__);
|
|
|
|
room->callLua(command, QJsonDocument(arr).toJson());
|
|
|
|
room->unlockLua(__FUNCTION__);
|
2022-01-24 02:23:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type & TYPE_REQUEST) {
|
|
|
|
this->requestId = requestId;
|
|
|
|
this->requestTimeout = packet[4].toInt();
|
|
|
|
|
|
|
|
if (type & DEST_CLIENT) {
|
2022-03-02 12:56:37 +00:00
|
|
|
qobject_cast<Client *>(parent())->callLua(command, jsonData);
|
2022-01-24 02:23:08 +00:00
|
|
|
} else {
|
2022-03-01 05:18:00 +00:00
|
|
|
// requesting server is not allowed
|
|
|
|
Q_ASSERT(false);
|
2022-01-24 02:23:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (type & TYPE_REPLY) {
|
|
|
|
QMutexLocker locker(&replyMutex);
|
|
|
|
|
|
|
|
if (requestId != this->expectedReplyId)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this->expectedReplyId = -1;
|
|
|
|
|
|
|
|
if (replyTimeout >= 0 && replyTimeout <
|
|
|
|
requestStartTime.secsTo(QDateTime::currentDateTime()))
|
|
|
|
return;
|
|
|
|
|
2022-03-02 12:56:37 +00:00
|
|
|
m_reply = jsonData;
|
2022-01-24 02:23:08 +00:00
|
|
|
// TODO: callback?
|
|
|
|
|
|
|
|
replyReadySemaphore.release();
|
|
|
|
if (extraReplyReadySemaphore) {
|
|
|
|
extraReplyReadySemaphore->release();
|
|
|
|
extraReplyReadySemaphore = nullptr;
|
|
|
|
}
|
|
|
|
locker.unlock();
|
|
|
|
emit replyReady();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|