qmlhandler.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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[1024];
  20. QUrl sendFileUrl = QUrl("");
  21. bool programActive = true;
  22. void QMLHandler::onExit() {
  23. write(outpipefd[1], "disconnect\n", strlen("disconnect\n"));
  24. }
  25. void QMLHandler::handleJSON(string buffer) {
  26. Json::Value root;
  27. Json::CharReaderBuilder builder;
  28. Json::CharReader *reader = builder.newCharReader();
  29. string jsonError;
  30. bool parsingSuccessful = reader->parse(
  31. buffer.c_str(), buffer.c_str() + buffer.size(), &root, &jsonError);
  32. if (!parsingSuccessful) {
  33. return;
  34. }
  35. const Json::Value command = root["command"];
  36. string cmd = command.asString();
  37. if (cmd == "status") {
  38. emit footerSetStatus(root["response"].asString().c_str());
  39. }
  40. else if (cmd == "close") {
  41. programActive = false;
  42. }
  43. }
  44. void QMLHandler::readPipeLoop() {
  45. unsigned int readOffset = 0;
  46. unsigned int pollCount = 0;
  47. struct pollfd inPipeStatus;
  48. inPipeStatus.fd = inpipefd[0];
  49. inPipeStatus.events = POLLIN;
  50. while (programActive) {
  51. poll(&inPipeStatus, 1, 100);
  52. if (inPipeStatus.revents & POLLIN) {
  53. readOffset += read(inpipefd[0], buf + readOffset, 1);
  54. pollCount = 0;
  55. } else {
  56. pollCount++;
  57. }
  58. if (pollCount > 9 && buf[0]) {
  59. buf[1023] = 0;
  60. buf[strlen(buf)] = 0;
  61. string cleanBuffer = buf + strcspn(buf, "\n") + 1;
  62. string receivedData = cleanBuffer.substr(0, cleanBuffer.size() - 1);
  63. emit log(QString::fromStdString(receivedData));
  64. qInfo() << QString::fromStdString(receivedData);
  65. handleJSON(receivedData);
  66. memset(buf, 0, 1024);
  67. pollCount = 0;
  68. readOffset = 0;
  69. }
  70. }
  71. }
  72. QMLHandler::QMLHandler(QObject *parent) : QObject(parent) {}
  73. // Sending
  74. void QMLHandler::onSendingSelectFileButton(QUrl url) {
  75. sendFileUrl = url.toLocalFile();
  76. emit log("File Selected: " + sendFileUrl.toString());
  77. emit sendingSetFileUrlText("Selected File: " + sendFileUrl.toString());
  78. emit sendingEnableSendButton();
  79. }
  80. void QMLHandler::onSendingSendFileButton() {
  81. QString command = "put " + sendFileUrl.toString() + "\n";
  82. write(outpipefd[1], command.toUtf8().constData(),
  83. strlen(command.toUtf8().constData()));
  84. }
  85. // Receiving
  86. void QMLHandler::onReceivingGetFileButton(QString fileName) {
  87. QString command = "get " + fileName + "\n";
  88. write(outpipefd[1], command.toUtf8().constData(),
  89. strlen(command.toUtf8().constData()));
  90. }
  91. // Messages
  92. void QMLHandler::onMessagesSendButton(QString msg) { emit message(msg); }
  93. // Settings
  94. void QMLHandler::onSettingsSwitchServerButton() {
  95. emit settingsOpenSwitchServerPopup();
  96. }
  97. // Ip Popup
  98. void QMLHandler::onIpPopupEnterIp(QString ip) {
  99. pid_t pid = 0;
  100. pipe(inpipefd);
  101. pipe(outpipefd);
  102. pid = fork();
  103. if (pid == 0) {
  104. // Child
  105. dup2(outpipefd[0], STDIN_FILENO);
  106. dup2(inpipefd[1], STDOUT_FILENO);
  107. // dup2(inpipefd[1], STDERR_FILENO);
  108. // ask kernel to deliver SIGTERM in case the parent dies
  109. prctl(PR_SET_PDEATHSIG, SIGTERM);
  110. // Set the path to the CLI - pass argument h (help) for now
  111. // TODO: Change hardcoded path
  112. execl("../../cli/build/ccats-cli", "ccats-cli", ip.toUtf8().constData(),
  113. "--machine", (char *)NULL);
  114. exit(1);
  115. }
  116. // TODO: Not hardcoded
  117. emit footerSetStatus("Connected to " + ip);
  118. close(outpipefd[0]);
  119. close(inpipefd[1]);
  120. std::thread(&QMLHandler::readPipeLoop, this).detach();
  121. }
  122. // Switch Popup
  123. void QMLHandler::onSwitchPopupEnterIp(QString ip) {
  124. qInfo() << "Switching to " << ip;
  125. }
  126. // Footer
  127. void QMLHandler::onFooterGetStatusButton() {
  128. write(outpipefd[1], "status\n", strlen("status\n"));
  129. }