ControlRequestHandler.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <native/AssetManager/ControlRequestHandler.h>
  9. #if !defined(Q_MOC_RUN)
  10. #include <QHostAddress>
  11. #include <QTcpSocket>
  12. #include <QTcpServer>
  13. #endif
  14. #include <native/assetprocessor.h>
  15. #include <native/utilities/ApplicationManagerBase.h>
  16. #include <AzCore/Casting/numeric_cast.h>
  17. #include <AzCore/Debug/Trace.h>
  18. ControlRequestHandler::ControlRequestHandler(ApplicationManagerBase* parent) : QObject(parent),
  19. m_applicationManager(parent)
  20. {
  21. connect(m_applicationManager, &ApplicationManagerBase::FullIdle, this, &ControlRequestHandler::AssetManagerIdleStateChange);
  22. StartListening(0);
  23. }
  24. ControlRequestHandler::~ControlRequestHandler()
  25. {
  26. }
  27. bool ControlRequestHandler::StartListening(unsigned short port)
  28. {
  29. if (!m_tcpServer)
  30. {
  31. m_tcpServer = new QTcpServer(this);
  32. }
  33. if (!m_tcpServer->isListening())
  34. {
  35. if (!m_tcpServer->listen(QHostAddress::LocalHost, port))
  36. {
  37. AZ_Error(AssetProcessor::ConsoleChannel, false, "Control Request Handler couldn't listen on requested port %d", port);
  38. return false;
  39. }
  40. port = m_tcpServer->serverPort();
  41. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control Port: %d\n", port);
  42. connect(m_tcpServer, &QTcpServer::newConnection, this, &ControlRequestHandler::GotConnection);
  43. AZ_TracePrintf(AssetProcessor::DebugChannel, "Asset Processor Control Request Handler listening on port %d\n", port);
  44. }
  45. return true;
  46. }
  47. void ControlRequestHandler::GotConnection()
  48. {
  49. if (m_tcpServer->hasPendingConnections())
  50. {
  51. QTcpSocket* newSocket = m_tcpServer->nextPendingConnection();
  52. connect(newSocket, &QTcpSocket::stateChanged, this, &ControlRequestHandler::SocketStateUpdate);
  53. connect(newSocket, &QTcpSocket::readyRead, this, &ControlRequestHandler::DataReceived);
  54. connect(newSocket, &QTcpSocket::disconnected, this, &ControlRequestHandler::Disconnected);
  55. m_listenSockets.push_back(newSocket);
  56. AZ_TracePrintf(AssetProcessor::DebugChannel, "Asset Processor Control Request Handler got new connection\n");
  57. if (newSocket->bytesAvailable())
  58. {
  59. AZ_TracePrintf(AssetProcessor::DebugChannel, "Asset Processor Control Request Handler socket had data available\n");
  60. ReadData(newSocket);
  61. }
  62. }
  63. }
  64. void ControlRequestHandler::SocketStateUpdate(QAbstractSocket::SocketState newState)
  65. {
  66. if (newState == QAbstractSocket::UnconnectedState)
  67. {
  68. m_listenSockets.removeOne(static_cast<QTcpSocket*>(QObject::sender()));
  69. }
  70. }
  71. void ControlRequestHandler::DataReceived()
  72. {
  73. QTcpSocket* incoming = static_cast<QTcpSocket*>(QObject::sender());
  74. ReadData(incoming);
  75. }
  76. void ControlRequestHandler::ReadData(QTcpSocket* incoming)
  77. {
  78. if (!incoming)
  79. {
  80. AZ_Error(AssetProcessor::DebugChannel, false, "Attempting to read from null QTcpSocket in ControlRequestHandler");
  81. return;
  82. }
  83. auto sentMessage = incoming->readAll().toStdString();
  84. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Got Control request %s\n", sentMessage.c_str());
  85. if (sentMessage == "quit")
  86. {
  87. QMetaObject::invokeMethod(parent(), "QuitRequested", Qt::QueuedConnection);
  88. }
  89. else if (sentMessage == "ping")
  90. {
  91. incoming->write("pong");
  92. }
  93. else if (sentMessage == "isidle")
  94. {
  95. bool isIdle = m_applicationManager->IsAssetProcessorManagerIdle();
  96. incoming->write(isIdle ? "true" : "false");
  97. }
  98. else if (sentMessage == "waitforidle")
  99. {
  100. bool isIdle = m_applicationManager->CheckFullIdle();
  101. if (isIdle)
  102. {
  103. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control request responding idle\n");
  104. incoming->write("idle");
  105. }
  106. else
  107. {
  108. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control request adding wait idle waiter\n");
  109. m_idleWaitSockets.push_back(incoming);
  110. }
  111. }
  112. else if (sentMessage == "signalidle")
  113. {
  114. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control request adding signal idle waiter\n");
  115. m_idleWaitSockets.push_back(incoming);
  116. }
  117. else if (sentMessage == "windowid")
  118. {
  119. incoming->write(AZStd::string::format("%lld", m_applicationManager->GetWindowId()).c_str());
  120. }
  121. }
  122. void ControlRequestHandler::Disconnected()
  123. {
  124. QTcpSocket* incoming = static_cast<QTcpSocket*>(QObject::sender());
  125. m_listenSockets.removeOne(incoming);
  126. incoming->deleteLater();
  127. }
  128. void ControlRequestHandler::AssetManagerIdleStateChange(bool isIdle)
  129. {
  130. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control Request Got idle state %d with %d waiters\n", isIdle, m_idleWaitSockets.size());
  131. if (!isIdle)
  132. {
  133. // We only currently care when transitioning to idle
  134. return;
  135. }
  136. for (auto& thisConnection : m_idleWaitSockets)
  137. {
  138. if (m_listenSockets.indexOf(thisConnection) != -1)
  139. {
  140. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Control request sending idle state to socket\n");
  141. thisConnection->write("idle");
  142. }
  143. }
  144. m_idleWaitSockets.clear();
  145. }