qmlhandler.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include <QGuiApplication>
  2. #include <csignal>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <iostream>
  6. #include <poll.h>
  7. #include <sys/prctl.h>
  8. #include <sys/wait.h>
  9. #include <thread>
  10. #include <unistd.h>
  11. #include "qmlhandler.h"
  12. #include <boost/asio.hpp>
  13. #include <iostream>
  14. #include <json/json.h>
  15. using boost::asio::buffer;
  16. using namespace std;
  17. int inpipefd[2];
  18. int outpipefd[2];
  19. char buf[1025];
  20. QUrl sendFileUrl = QUrl("");
  21. bool programActive = true;
  22. QMLHandler::QMLHandler(QObject *parent) : QObject(parent) {}
  23. void QMLHandler::onExit() {
  24. write(outpipefd[1], "disconnect\n", strlen("disconnect\n"));
  25. }
  26. // This method gets a string and tries to read it as Json
  27. // If it fails to do so, return and do nothing, else handle the content
  28. void QMLHandler::handleJSON(string buffer) {
  29. Json::Value root;
  30. Json::CharReaderBuilder builder;
  31. Json::CharReader *reader = builder.newCharReader();
  32. string jsonError;
  33. // Try to parse the string as Json and store the result of the pasring in a
  34. // boolean
  35. bool parsingSuccessful = reader->parse(
  36. buffer.c_str(), buffer.c_str() + buffer.size(), &root, &jsonError);
  37. // If the string is not correct Json, return
  38. if (!parsingSuccessful) {
  39. return;
  40. }
  41. const Json::Value command = root["command"];
  42. string cmd = command.asString();
  43. if (cmd == "status") {
  44. emit footerSetStatus(root["response"].asString().c_str());
  45. }
  46. else if (cmd == "close") {
  47. programActive = false;
  48. }
  49. else if (cmd == "list") {
  50. emit receivingClearFileList();
  51. // Get the array of file Names
  52. auto fileNames = root["names"];
  53. for (int i = 0; i < fileNames.size(); i++) {
  54. emit receivingListFile(
  55. QString::fromStdString(fileNames[i].asString().c_str()));
  56. }
  57. }
  58. }
  59. // This method is a loop which runs in a seperate thread.
  60. // If will read the Input Pipe, which containts the string that get printed
  61. // on stdout by the CLI/Server, and calls handleJSON with the read content
  62. // one it reads a newline.
  63. void QMLHandler::readPipeLoop() {
  64. unsigned int readOffset = 0;
  65. unsigned int pollCount = 0;
  66. struct pollfd inPipeStatus;
  67. inPipeStatus.fd = inpipefd[0];
  68. inPipeStatus.events = POLLIN;
  69. while (programActive) {
  70. poll(&inPipeStatus, 1, 100);
  71. if (inPipeStatus.revents & POLLIN) {
  72. readOffset += read(inpipefd[0], buf + readOffset, 1);
  73. pollCount = 0;
  74. } else {
  75. pollCount++;
  76. }
  77. if (pollCount > 9 && buf[0]) {
  78. buf[1024] = 0;
  79. buf[strlen(buf)] = 0;
  80. string cleanBuffer = buf + strcspn(buf, "\n") + 1;
  81. string receivedData = cleanBuffer.substr(0, cleanBuffer.size() - 1);
  82. emit log(QString::fromStdString(receivedData));
  83. qInfo() << QString::fromStdString(receivedData);
  84. handleJSON(receivedData);
  85. memset(buf, 0, 1024);
  86. pollCount = 0;
  87. readOffset = 0;
  88. }
  89. }
  90. }
  91. // ### QML Handlers ###
  92. // Sending
  93. void QMLHandler::onSendingSelectFileButton(QUrl url) {
  94. sendFileUrl = url.toLocalFile();
  95. emit log("File Selected: " + sendFileUrl.toString());
  96. emit sendingSetFileUrlText("Selected File: " + sendFileUrl.toString());
  97. emit sendingEnableSendButton();
  98. }
  99. void QMLHandler::onSendingSendFileButton() {
  100. QString command = "put " + sendFileUrl.toString() + "\n";
  101. write(outpipefd[1], command.toUtf8().constData(),
  102. strlen(command.toUtf8().constData()));
  103. }
  104. void QMLHandler::onSendingClearSelectionButton() {
  105. sendFileUrl = QUrl("");
  106. emit log("Cleared Selection");
  107. emit sendingSetFileUrlText("Selected File: None");
  108. emit sendingDisableSendButton();
  109. }
  110. // Receiving
  111. void QMLHandler::onReceivingListFilesButton() {
  112. write(outpipefd[1], "list\n", strlen("list\n"));
  113. }
  114. void QMLHandler::onReceivingGetFileButton(QString fileName) {
  115. QString command = "get " + fileName + "\n";
  116. write(outpipefd[1], command.toUtf8().constData(),
  117. strlen(command.toUtf8().constData()));
  118. }
  119. // Messages
  120. void QMLHandler::onMessagesSendButton(QString msg) { emit message(msg); }
  121. // Settings
  122. void QMLHandler::onSettingsSwitchServerButton() {
  123. emit settingsOpenSwitchServerPopup();
  124. }
  125. // Ip Popup
  126. void QMLHandler::onIpPopupEnterIp(QString ip) {
  127. pid_t pid = 0;
  128. pipe(inpipefd);
  129. pipe(outpipefd);
  130. pid = fork();
  131. if (pid == 0) {
  132. // Child
  133. dup2(outpipefd[0], STDIN_FILENO);
  134. dup2(inpipefd[1], STDOUT_FILENO);
  135. // dup2(inpipefd[1], STDERR_FILENO);
  136. // ask kernel to deliver SIGTERM in case the parent dies
  137. prctl(PR_SET_PDEATHSIG, SIGTERM);
  138. // Set the path to the CLI - pass argument h (help) for now
  139. // TODO: Change hardcoded path
  140. execl("../../cli/build/ccats-cli", "ccats-cli", ip.toUtf8().constData(),
  141. "--machine", (char *)NULL);
  142. exit(1);
  143. }
  144. // TODO: Not hardcoded
  145. emit footerSetStatus("Connected to " + ip);
  146. close(outpipefd[0]);
  147. close(inpipefd[1]);
  148. std::thread(&QMLHandler::readPipeLoop, this).detach();
  149. }
  150. // Switch Popup
  151. void QMLHandler::onSwitchPopupEnterIp(QString ip) {
  152. qInfo() << "Switching to " << ip;
  153. }
  154. // Footer
  155. void QMLHandler::onFooterGetStatusButton() {
  156. write(outpipefd[1], "status\n", strlen("status\n"));
  157. }