H-a-y-K

Untitled

Mar 15th, 2020
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "hichess_server.h"
  2. #include <QThread>
  3.  
  4. #define UDP_SERVER_PORT 45454
  5. #define UDP_CLIENT_PORT 45455
  6. #define WEB_PORT 54545
  7.  
  8.  
  9. Player::Player(const QString& name, QWebSocket *wsocket)
  10.     : m_wsocket(wsocket)
  11.     , m_name(name)
  12. {}
  13.  
  14. bool Player::operator==(const Player &other) const
  15. {
  16.     return QString::compare(m_name, other.getName(), Qt::CaseInsensitive);
  17. }
  18.  
  19. Game::Game(const PlayerPair &players)
  20.     : m_name(QString("%1 vs %2").arg(players.first.getName(), players.second.getName()))
  21.     , m_players(QRandomGenerator::global()->bounded(1) ?
  22.                     players :
  23.                     qMakePair(players.second, players.first))
  24. {}
  25.  
  26. bool Game::operator==(const Game &other) const
  27. {
  28.     return QString::compare(m_name, other.getName(), Qt::CaseInsensitive);
  29. }
  30.  
  31. HichessServer::HichessServer(QObject *parent)
  32.     : QObject(parent)
  33. {
  34.     m_udpServer = new QUdpSocket(this);
  35.     m_webServer = new QWebSocketServer("HichessServer", QWebSocketServer::NonSecureMode, this);
  36.  
  37.     connect(m_udpServer, &QUdpSocket::readyRead, this, &HichessServer::processPendingDatagrams);
  38.     connect(m_webServer, &QWebSocketServer::newConnection, this, &HichessServer::onNewConnection);
  39.     connect(m_webServer, &QWebSocketServer::serverError, this,
  40.             [](QWebSocketProtocol::CloseCode closeCode) { qDebug() << Q_FUNC_INFO << closeCode; });
  41.  
  42.     QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
  43.     foreach (QNetworkInterface interface, interfaces)
  44.         if (interface.isValid() &&
  45.             !interface.flags().testFlag(QNetworkInterface::IsLoopBack) &&
  46.             !interface.flags().testFlag(QNetworkInterface::IsPointToPoint) &&
  47.             interface.flags().testFlag(QNetworkInterface::IsUp) &&
  48.             interface.flags().testFlag(QNetworkInterface::IsRunning))
  49.         {
  50.             QList<QNetworkAddressEntry> addresses = interface.addressEntries();
  51.             foreach (QNetworkAddressEntry address, addresses)
  52.                 if (!address.ip().isNull() &&
  53.                     !address.ip().isLoopback() &&
  54.                     address.ip().protocol() == QUdpSocket::IPv4Protocol)
  55.                 {
  56.                     qDebug() << Q_FUNC_INFO << "IP: " << address.ip().toString();
  57.                     qDebug() << Q_FUNC_INFO << "Bound: " << m_udpServer->bind(address.ip(), UDP_SERVER_PORT, QUdpSocket::ShareAddress);
  58.                     qDebug() << Q_FUNC_INFO << "Port: " << m_udpServer->localAddress() << m_udpServer->localPort();
  59.                     qDebug() << Q_FUNC_INFO << "Listening: " << m_webServer->listen(address.ip(), WEB_PORT);
  60.                     return;
  61.                 }
  62.         }
  63. }
  64.  
  65. void HichessServer::processPendingDatagrams()
  66. {
  67.     QUdpSocket *socket = qobject_cast<QUdpSocket*>(sender());
  68.     if (socket && socket->hasPendingDatagrams()) {
  69.         QNetworkDatagram datagram = socket->receiveDatagram();
  70.         qDebug() << Q_FUNC_INFO << "Datagram data: " << datagram.data();
  71.  
  72.         if (datagram.data().startsWith("User = ")) {
  73.             qDebug() << Q_FUNC_INFO << "Datagram data is valid, parsing...";
  74.             QString username = datagram.data().mid(7);
  75.             QRegularExpression rx("[A-Za-z0-9_]{6,15}");
  76.  
  77.             if (rx.match(username).hasMatch()) {
  78.                 qDebug() << Q_FUNC_INFO << "Parsed username is valid...";
  79.                 auto found = std::find_if(m_allPlayers.begin(), m_allPlayers.end(), [username](Player p) {
  80.                     return p.getName() == username;
  81.                 });
  82.  
  83.                 if (found == m_allPlayers.end()) {
  84.                     qDebug() << Q_FUNC_INFO << username << "Username is not occupied";
  85.                     qDebug() << Q_FUNC_INFO << "Url: " << m_webServer->serverUrl().toString().toUtf8();
  86.                     m_usernameQueue.enqueue(username);
  87.                     socket->writeDatagram(m_webServer->serverUrl().toString().toUtf8(), datagram.senderAddress(), UDP_CLIENT_PORT);
  88.                 } else
  89.                     qDebug() << Q_FUNC_INFO << username << " username is already occupied";
  90.             } else
  91.                 qDebug() << Q_FUNC_INFO << username << " is not a valid username";
  92.         }
  93.     }
  94. }
  95.  
  96. void HichessServer::addClient(QWebSocket *client)
  97. {
  98.     if (client == nullptr) {
  99.         qDebug() << Q_FUNC_INFO << " Client is nullptr";
  100.         return;
  101.     }
  102.     qDebug() << Q_FUNC_INFO << "Client: " << client;
  103.  
  104.     connect(client, &QWebSocket::disconnected, this, [this, client]() {
  105.         qDebug() << Q_FUNC_INFO << client << "disconnected";
  106.         removeClient(client);
  107.     });
  108.     connect(client, &QWebSocket::textMessageReceived, this, [](){});
  109.     connect(client, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error),
  110.         [=](QAbstractSocket::SocketError error){ qDebug() << Q_FUNC_INFO << error; });
  111.     connect(client, &QObject::destroyed, this, []() {qDebug() << Q_FUNC_INFO << "destroyed"; });
  112.  
  113.     if (!m_usernameQueue.isEmpty()) {
  114.         qDebug() << Q_FUNC_INFO << "There are queued usernames";
  115.  
  116.         QString username = m_usernameQueue.dequeue();
  117.         qDebug() << Q_FUNC_INFO << "Username: " << username;
  118.  
  119.         m_playerQueue.enqueue({username, client});
  120.         m_allPlayers.append({username, client});
  121.  
  122.         if (m_playerQueue.size() > 1) {
  123.             qDebug() << Q_FUNC_INFO << "There are more than 1 queued players. Found pair for a game...";
  124.             PlayerPair players = {m_playerQueue.dequeue(), m_playerQueue.dequeue()};
  125.  
  126.             Game game(players);
  127.             m_games.append(game);
  128.         }
  129.         foreach (auto p, m_allPlayers)
  130.             qDebug() << Q_FUNC_INFO << "Players: " << p.getName();
  131.         foreach (auto g, m_games)
  132.             qDebug() << Q_FUNC_INFO << "Games: " << g.getName();
  133.     } else
  134.         qDebug() << Q_FUNC_INFO << "There are no queued usernames";
  135. }
  136.  
  137. void HichessServer::removeClient(QWebSocket *client)
  138. {
  139.     auto p = std::find_if(m_allPlayers.begin(), m_allPlayers.end(), [client](const Player &p){ return p.getWSocket() == client; });
  140.     if (p != m_allPlayers.end()){
  141.         qDebug() << Q_FUNC_INFO << "Found the client to remove";
  142.         qDebug() << Q_FUNC_INFO << "Username: " << p->getName() << ", socket: " << client;
  143.  
  144.         m_allPlayers.removeAll(*p);
  145.         m_playerQueue.removeAll(*p);
  146.  
  147.         foreach (Game g, m_games) {
  148.             if (g.getWhite() == *p) {
  149.                 qDebug() << Q_FUNC_INFO << "Found game with insufficient players. White player is missing.";
  150.                 m_games.removeAll(g);
  151.                 g.getBlack().getWSocket()->sendTextMessage(p->getName() + " left the game");
  152.                 break;
  153.             } else if (g.getBlack() == *p) {
  154.                 qDebug() << Q_FUNC_INFO << "Found game with insufficient players. Black player is missing.";
  155.                 m_games.removeAll(g);
  156.                 g.getBlack().getWSocket()->sendTextMessage(p->getName() + " left the game");
  157.                 break;
  158.             } else
  159.                 qDebug() << Q_FUNC_INFO << "Client is not inside a game";
  160.         }
  161.         p->getWSocket()->deleteLater();
  162.         qDebug() << Q_FUNC_INFO << p->getName() << " left the game";
  163.     }
  164. }
  165.  
  166. void HichessServer::onNewConnection()
  167. {
  168.     qDebug() << Q_FUNC_INFO;
  169.     auto cli = m_webServer->nextPendingConnection();
  170.     addClient(cli);
  171. }
  172.  
  173. void HichessServer::onTextMessageReceived()
  174. {
  175.  
  176. }
Add Comment
Please, Sign In to add comment