SshClient.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. GNU General Public License version 3 notice
  3. Copyright (C) 2012 Mihawk <luiz@netdome.biz>. All rights reserved.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see < http://www.gnu.org/licenses/ >.
  14. */
  15. #include "SshClient.h"
  16. #include <QProcess>
  17. #include <QRegExp>
  18. #include <QDateTime>
  19. #include <QTimerEvent>
  20. #include <QStringList>
  21. #include <QDebug>
  22. SshClient::SshClient(QObject *parent) :
  23. QObject(parent),
  24. myProcess(new QProcess(this)),
  25. myCommandRegex(new QRegExp("^([0-9]{4}-[0-9]{2}-[0-9]{2}\\s[0-9]{2}:[0-9]{2}:[0-9]{2}\\s\\+[0-9]{4}):\\s([A-Za-z]+):?\\s?(.*)$")),
  26. myConnectedFlag(false),
  27. myConnectionTimerID(0),
  28. myPingTimerID(0),
  29. myPongTimerID(0),
  30. myClients(new QStringList())
  31. {
  32. connect(myProcess, SIGNAL(readyRead()), SLOT(read()));
  33. connect(myProcess, SIGNAL(finished(int)), SLOT(exited(int)));
  34. }
  35. SshClient::~SshClient()
  36. {
  37. delete myCommandRegex;
  38. delete myClients;
  39. }
  40. bool SshClient::isConnected() const
  41. {
  42. return myConnectedFlag;
  43. }
  44. void SshClient::read()
  45. {
  46. QString data(myProcess->readAll().trimmed());
  47. if(data.isEmpty())
  48. return;
  49. QStringList lines = data.split("\n", QString::SkipEmptyParts);
  50. QString line;
  51. foreach(line, lines)
  52. {
  53. line = line.trimmed();
  54. if(myCommandRegex->indexIn(line) != -1)
  55. {
  56. QDateTime time = QDateTime::fromString(myCommandRegex->capturedTexts().at(1).section(' ', 0, 1), "yyyy-MM-dd HH:mm:ss");
  57. parse(time,
  58. myCommandRegex->capturedTexts().at(2),
  59. myCommandRegex->capturedTexts().at(3)
  60. );
  61. }
  62. }
  63. }
  64. void SshClient::exited(int exitCode)
  65. {
  66. qDebug() << "finished" << exitCode;
  67. }
  68. void SshClient::ping()
  69. {
  70. write("PING\n");
  71. myPingTimerID = startTimer(30000);
  72. }
  73. void SshClient::pong()
  74. {
  75. killTimer(myPingTimerID);
  76. myPongTimerID = startTimer(30000);
  77. }
  78. void SshClient::write(const QString &data)
  79. {
  80. myProcess->write(data.toAscii());
  81. myProcess->waitForBytesWritten();
  82. }
  83. void SshClient::parse(const QDateTime &time, const QString &command, const QString &commandData)
  84. {
  85. QString cmdData = commandData.trimmed();
  86. if(cmdData.startsWith(": "))
  87. cmdData.remove(0, 2);
  88. /* JOINED - Another user has just joined central */
  89. if(command == "JOINED")
  90. {
  91. QRegExp a("^User '([a-zA-Z]+)'.+$");
  92. if(a.indexIn(commandData) == -1)
  93. {
  94. if(!myClients->contains(a.capturedTexts().at(1)))
  95. myClients->push_back(a.capturedTexts().at(1));
  96. }
  97. return;
  98. }
  99. /* PARTED - Another user has left central */
  100. if(command == "PARTED")
  101. {
  102. QRegExp a("^User '([a-zA-Z]+)'.+$");
  103. if(a.indexIn(commandData) == -1)
  104. myClients->removeAll(a.capturedTexts().at(1));
  105. return;
  106. }
  107. /* HELLO - Server acknowledge */
  108. if(command == "HELLO")
  109. {
  110. ping();
  111. myConnectedFlag = true;
  112. killTimer(myConnectionTimerID);
  113. emit connected();
  114. return;
  115. }
  116. /* PING PONG - The connection is still up */
  117. if(command == "PONG")
  118. {
  119. pong();
  120. return;
  121. }
  122. /* SYS - Central generic message */
  123. if(command == "SYS")
  124. {
  125. qDebug() << "Central Message" << commandData;
  126. return;
  127. }
  128. /* BC - Broadcast order from central */
  129. if(command == "BC")
  130. {
  131. QRegExp a("^([A-Za-z0-9]+) (.+),(.+),(.+),'(.+)','(.+)'$");
  132. if(a.indexIn(commandData) == -1)
  133. return;
  134. qDebug() << "Broadcast Request" << commandData;
  135. // BC 0x0hash hash QDEV,-dev-,qw://123.123,'testuser','test, with '',``twists''$ hehe'
  136. return;
  137. }
  138. qDebug() << time << command << cmdData;
  139. }
  140. bool SshClient::connectToHost(const QString &user, const QString &host)
  141. {
  142. myProcess->start("ssh", QStringList() << user + "@" + host);
  143. bool r = myProcess->waitForStarted();
  144. if(!r)
  145. return false;
  146. else
  147. {
  148. myConnectionTimerID = startTimer(30000);
  149. return true;
  150. }
  151. }
  152. void SshClient::disconnectFromHost()
  153. {
  154. killTimer(myConnectionTimerID);
  155. killTimer(myPingTimerID);
  156. killTimer(myPongTimerID);
  157. myProcess->terminate();
  158. myProcess->waitForFinished();
  159. myConnectedFlag = false;
  160. }
  161. void SshClient::timerEvent(QTimerEvent *e)
  162. {
  163. if(e->timerId() == myConnectionTimerID)
  164. {
  165. disconnectFromHost();
  166. emit error(ConnectionTimedOutError);
  167. return;
  168. }
  169. if(e->timerId() == myPingTimerID)
  170. {
  171. disconnectFromHost();
  172. emit error(ConnectionTimedOutError);
  173. return;
  174. }
  175. if(e->timerId() == myPongTimerID)
  176. {
  177. killTimer(myPongTimerID);
  178. ping();
  179. return;
  180. }
  181. }