File indexing completed on 2024-05-05 05:40:33

0001 #include "network/rserver.h"
0002 #include <QDebug>
0003 #include <QMessageLogger>
0004 #include <network/serverconnectionmanager.h>
0005 
0006 #include "network/timeaccepter.h"
0007 #include "network/upnp/upnpnat.h"
0008 
0009 RServer::RServer(const QMap<QString, QVariant>& parameter, bool internal, QObject* parent)
0010     : QTcpServer(parent), m_corConnection(new TimeAccepter()), m_data(parameter),m_internal(internal)
0011 {
0012     if(m_data.contains("ThreadCount"))
0013         m_threadCount= m_data.value("ThreadCount", m_threadCount).toInt();
0014     connect(this, &RServer::portChanged, this, &RServer::runUpnpNat);
0015     runUpnpNat();
0016 }
0017 
0018 RServer::~RServer()
0019 {
0020     emit eventOccured(QStringLiteral("Server Destructor"), LogController::Debug);
0021     for(auto& info : m_threadPool)
0022     {
0023         info.m_thread->quit();
0024         info.m_thread->wait(1000);
0025     }
0026 }
0027 
0028 void RServer::runUpnpNat()
0029 {
0030     auto nat= new UpnpNat(this);
0031     nat->init(5, 10);
0032     connect(nat, &UpnpNat::discoveryEnd, this, [this, nat](bool b) {
0033 
0034         qDebug() << "discover ends" << nat;
0035         if(b)
0036            nat->addPortMapping("Roliserver", nat->localIp(), m_port, m_port, "TCP");
0037     });
0038     connect(nat, &UpnpNat::statusChanged, this, [this, nat]() {
0039         if(nat->status() == UpnpNat::NAT_STAT::NAT_ADD)
0040         {
0041             emit eventOccured(tr("[Upnp] Port mapping has been done"), LogController::LogLevel::Features);
0042             nat->deleteLater();
0043         }
0044     });
0045 
0046     connect(nat, &UpnpNat::lastErrorChanged, this,
0047             [this, nat]() { emit eventOccured(nat->lastError(), LogController::LogLevel::Error); });
0048 
0049     nat->discovery();
0050 }
0051 
0052 bool RServer::listen()
0053 {
0054     if(!QTcpServer::listen(QHostAddress::Any, m_port))
0055     {
0056         setState(RServer::Error);
0057         return false;
0058     }
0059     emit eventOccured(QStringLiteral("Start Listening"), LogController::Info);
0060 
0061     m_connectionsManager.reset(new ServerConnectionManager(m_data));
0062     m_updater.reset(new ServerManagerUpdater(m_connectionsManager.get(), m_internal));
0063     m_connectionThread.reset(new QThread);
0064 
0065     connect(this, &RServer::finished, m_connectionsManager.get(), &ServerConnectionManager::quit, Qt::QueuedConnection);
0066     connect(this, &RServer::accepting, m_connectionsManager.get(), &ServerConnectionManager::accept,
0067             Qt::QueuedConnection);
0068     connect(m_connectionsManager.get(), &ServerConnectionManager::finished, this, &RServer::complete,
0069             Qt::QueuedConnection);
0070 
0071     for(int i= 0; i < m_threadCount; ++i)
0072     {
0073         ThreadInfo info{new QThread(this), 0};
0074         m_threadPool.append(info);
0075         info.m_thread->start();
0076     }
0077 
0078     m_connectionsManager->moveToThread(m_connectionThread.get());
0079     m_updater->moveToThread(m_connectionThread.get());
0080 
0081     m_connectionThread->start();
0082 
0083     setState(RServer::Listening);
0084 
0085     return true;
0086 }
0087 
0088 void RServer::close()
0089 {
0090     emit finished();
0091     QTcpServer::close();
0092     setState(RServer::Stopped);
0093 }
0094 
0095 qint64 RServer::port()
0096 {
0097     return m_port;
0098 }
0099 
0100 bool RServer::internal() const
0101 {
0102     return m_internal;
0103 }
0104 
0105 int RServer::threadCount() const
0106 {
0107     return m_threadCount;
0108 }
0109 
0110 RServer::ServerState RServer::state() const
0111 {
0112     return m_state;
0113 }
0114 
0115 void RServer::setPort(int p)
0116 {
0117     if(p == m_port)
0118         return;
0119     m_port= p;
0120     emit portChanged();
0121 }
0122 
0123 void RServer::incomingConnection(qintptr descriptor)
0124 {
0125     emit eventOccured(QStringLiteral("incoming Connection"), LogController::Debug);
0126     if(!m_corConnection->runAccepter(m_data))
0127         return;
0128 
0129     ServerConnection* connection= new ServerConnection(nullptr, nullptr);
0130     accept(descriptor, connection);
0131 }
0132 
0133 void RServer::accept(qintptr descriptor, ServerConnection* connection)
0134 {
0135     if(m_threadPool.isEmpty())
0136     {
0137         emit eventOccured(QStringLiteral("threadpool is empty - server is stopped"), LogController::Error);
0138         return;
0139     }
0140 
0141     auto it= std::min_element(
0142         std::begin(m_threadPool), std::end(m_threadPool),
0143         [](const ThreadInfo& a, const ThreadInfo& b) { return a.m_connectionCount < b.m_connectionCount; });
0144 
0145     if(it == std::end(m_threadPool))
0146     {
0147         emit eventOccured(QStringLiteral("No thread available - server is stopped"), LogController::Error);
0148         return;
0149     }
0150 
0151     it->m_connectionCount++;
0152     connection->moveToThread(it->m_thread);
0153     emit accepting(descriptor, connection);
0154 }
0155 
0156 void RServer::setState(const ServerState& state)
0157 {
0158     if(state == m_state)
0159         return;
0160     m_state= state;
0161     emit stateChanged(m_state);
0162 
0163     emit eventOccured(QStringLiteral("State Changed to %1").arg(state), LogController::Info);
0164 
0165     if(m_state == Error)
0166         emit eventOccured(errorString(), LogController::Error);
0167 }
0168 
0169 void RServer::complete()
0170 {
0171     if(!m_connectionThread)
0172     {
0173         emit eventOccured(QStringLiteral("exiting complete there was no thread!"), LogController::Warning);
0174         return;
0175     }
0176 
0177     m_connectionsManager.release();
0178 
0179     qDebug() << this << "Quitting thread";
0180     m_connectionThread->quit();
0181     m_connectionThread->wait();
0182 
0183     m_connectionThread.release();
0184 
0185     emit eventOccured(QStringLiteral("Rserver Complete"), LogController::Info);
0186     emit completed();
0187 }