Advertisement
H-a-y-K

Untitled

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