Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "hichess_server.h"
- #include <QThread>
- #define UDP_SERVER_PORT 45454
- #define UDP_CLIENT_PORT 45455
- #define WEB_PORT 54545
- Player::Player(const QString& name, QWebSocket *wsocket)
- : m_wsocket(wsocket)
- , m_name(name)
- {}
- bool Player::operator==(const Player &other) const
- {
- return QString::compare(m_name, other.getName(), Qt::CaseInsensitive);
- }
- Game::Game(const PlayerPair &players)
- : m_name(QString("%1 vs %2").arg(players.first.getName(), players.second.getName()))
- , m_players(QRandomGenerator::global()->bounded(1) ?
- players :
- qMakePair(players.second, players.first))
- {}
- bool Game::operator==(const Game &other) const
- {
- return QString::compare(m_name, other.getName(), Qt::CaseInsensitive);
- }
- HichessServer::HichessServer(QObject *parent)
- : QObject(parent)
- {
- m_udpServer = new QUdpSocket(this);
- m_webServer = new QWebSocketServer("HichessServer", QWebSocketServer::NonSecureMode, this);
- connect(m_udpServer, &QUdpSocket::readyRead, this, &HichessServer::processPendingDatagrams);
- connect(m_webServer, &QWebSocketServer::newConnection, this, &HichessServer::onNewConnection);
- connect(m_webServer, &QWebSocketServer::serverError, this,
- [](QWebSocketProtocol::CloseCode closeCode) { qDebug() << Q_FUNC_INFO << closeCode; });
- QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
- foreach (QNetworkInterface interface, interfaces)
- if (interface.isValid() &&
- !interface.flags().testFlag(QNetworkInterface::IsLoopBack) &&
- !interface.flags().testFlag(QNetworkInterface::IsPointToPoint) &&
- interface.flags().testFlag(QNetworkInterface::IsUp) &&
- interface.flags().testFlag(QNetworkInterface::IsRunning))
- {
- QList<QNetworkAddressEntry> addresses = interface.addressEntries();
- foreach (QNetworkAddressEntry address, addresses)
- if (!address.ip().isNull() &&
- !address.ip().isLoopback() &&
- address.ip().protocol() == QUdpSocket::IPv4Protocol)
- {
- qDebug() << Q_FUNC_INFO << "IP: " << address.ip().toString();
- qDebug() << Q_FUNC_INFO << "Bound: " << m_udpServer->bind(address.ip(), UDP_SERVER_PORT, QUdpSocket::ShareAddress);
- qDebug() << Q_FUNC_INFO << "Port: " << m_udpServer->localAddress() << m_udpServer->localPort();
- qDebug() << Q_FUNC_INFO << "Listening: " << m_webServer->listen(address.ip(), WEB_PORT);
- return;
- }
- }
- }
- void HichessServer::processPendingDatagrams()
- {
- QUdpSocket *socket = qobject_cast<QUdpSocket*>(sender());
- if (socket && socket->hasPendingDatagrams()) {
- QNetworkDatagram datagram = socket->receiveDatagram();
- qDebug() << Q_FUNC_INFO << "Datagram data: " << datagram.data();
- if (datagram.data().startsWith("User = ")) {
- qDebug() << Q_FUNC_INFO << "Datagram data is valid, parsing...";
- QString username = datagram.data().mid(7);
- QRegularExpression rx("[A-Za-z0-9_]{6,15}");
- if (rx.match(username).hasMatch()) {
- qDebug() << Q_FUNC_INFO << "Parsed username is valid...";
- auto found = std::find_if(m_allPlayers.begin(), m_allPlayers.end(), [username](Player p) {
- return p.getName() == username;
- });
- if (found == m_allPlayers.end()) {
- qDebug() << Q_FUNC_INFO << username << "Username is not occupied";
- qDebug() << Q_FUNC_INFO << "Url: " << m_webServer->serverUrl().toString().toUtf8();
- m_usernameQueue.enqueue(username);
- socket->writeDatagram(m_webServer->serverUrl().toString().toUtf8(), datagram.senderAddress(), UDP_CLIENT_PORT);
- } else
- qDebug() << Q_FUNC_INFO << username << " username is already occupied";
- } else
- qDebug() << Q_FUNC_INFO << username << " is not a valid username";
- }
- }
- }
- void HichessServer::addClient(QWebSocket *client)
- {
- if (client == nullptr) {
- qDebug() << Q_FUNC_INFO << " Client is nullptr";
- return;
- }
- qDebug() << Q_FUNC_INFO << "Client: " << client;
- connect(client, &QWebSocket::disconnected, this, [this, client]() {
- qDebug() << Q_FUNC_INFO << client << "disconnected";
- removeClient(client);
- });
- connect(client, &QWebSocket::textMessageReceived, this, [](){});
- connect(client, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
- [=](QAbstractSocket::SocketError error){ qDebug() << Q_FUNC_INFO << error; });
- connect(client, &QObject::destroyed, this, []() {qDebug() << Q_FUNC_INFO << "destroyed"; });
- if (!m_usernameQueue.isEmpty()) {
- qDebug() << Q_FUNC_INFO << "There are queued usernames";
- QString username = m_usernameQueue.dequeue();
- qDebug() << Q_FUNC_INFO << "Username: " << username;
- m_playerQueue.enqueue({username, client});
- m_allPlayers.append({username, client});
- if (m_playerQueue.size() > 1) {
- qDebug() << Q_FUNC_INFO << "There are more than 1 queued players. Found pair for a game...";
- PlayerPair players = {m_playerQueue.dequeue(), m_playerQueue.dequeue()};
- Game game(players);
- m_games.append(game);
- }
- foreach (auto p, m_allPlayers)
- qDebug() << Q_FUNC_INFO << "Players: " << p.getName();
- foreach (auto g, m_games)
- qDebug() << Q_FUNC_INFO << "Games: " << g.getName();
- } else
- qDebug() << Q_FUNC_INFO << "There are no queued usernames";
- }
- void HichessServer::removeClient(QWebSocket *client)
- {
- auto p = std::find_if(m_allPlayers.begin(), m_allPlayers.end(), [client](const Player &p){ return p.getWSocket() == client; });
- if (p != m_allPlayers.end()){
- qDebug() << Q_FUNC_INFO << "Found the client to remove";
- qDebug() << Q_FUNC_INFO << "Username: " << p->getName() << ", socket: " << client;
- m_allPlayers.removeAll(*p);
- m_playerQueue.removeAll(*p);
- foreach (Game g, m_games) {
- if (g.getWhite() == *p) {
- qDebug() << Q_FUNC_INFO << "Found game with insufficient players. White player is missing.";
- m_games.removeAll(g);
- g.getBlack().getWSocket()->sendTextMessage(p->getName() + " left the game");
- break;
- } else if (g.getBlack() == *p) {
- qDebug() << Q_FUNC_INFO << "Found game with insufficient players. Black player is missing.";
- m_games.removeAll(g);
- g.getBlack().getWSocket()->sendTextMessage(p->getName() + " left the game");
- break;
- } else
- qDebug() << Q_FUNC_INFO << "Client is not inside a game";
- }
- p->getWSocket()->deleteLater();
- qDebug() << Q_FUNC_INFO << p->getName() << " left the game";
- }
- }
- void HichessServer::onNewConnection()
- {
- qDebug() << Q_FUNC_INFO;
- auto cli = m_webServer->nextPendingConnection();
- addClient(cli);
- }
- void HichessServer::onTextMessageReceived()
- {
- }
Add Comment
Please, Sign In to add comment