sdbconnector.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Jarek Pelczar <jpelczar@gmail.com>
  4. **
  5. ** This file is part of Qt Creator.
  6. **
  7. ** Commercial License Usage
  8. ** Licensees holding valid commercial Qt licenses may use this file in
  9. ** accordance with the commercial license agreement provided with the
  10. ** Software or, alternatively, in accordance with the terms contained in
  11. ** a written agreement between you and Digia. For licensing terms and
  12. ** conditions see http://qt.digia.com/licensing. For further information
  13. ** use the contact form at http://qt.digia.com/contact-us.
  14. **
  15. ** GNU Lesser General Public License Usage
  16. ** Alternatively, this file may be used under the terms of the GNU Lesser
  17. ** General Public License version 2.1 as published by the Free Software
  18. ** Foundation and appearing in the file LICENSE.LGPL included in the
  19. ** packaging of this file. Please review the following information to
  20. ** ensure the GNU Lesser General Public License version 2.1 requirements
  21. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  22. **
  23. ** In addition, as a special exception, Digia gives you certain additional
  24. ** rights. These rights are described in the Digia Qt LGPL Exception
  25. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  26. **
  27. ****************************************************************************/
  28. #include "sdbconnector.h"
  29. #include "sdbconstants.h"
  30. #include "sdbpacketutils.h"
  31. #include <QHostAddress>
  32. #include <QDebug>
  33. #include <QFileInfo>
  34. #include <coreplugin/id.h>
  35. namespace Tizen {
  36. SdbConnector::SdbConnector(QObject *parent) :
  37. QObject(parent),
  38. m_socket(NULL),
  39. m_sdbProcess(NULL),
  40. m_state(SdbDisconnected),
  41. m_sdbPort(DefaultServerPort),
  42. m_startWait(NULL),
  43. m_retry(0)
  44. {
  45. m_startWait = new QTimer(this);
  46. connect(m_startWait, SIGNAL(timeout()), SLOT(_q_startWaitTimeout()));
  47. m_startWait->setInterval(1000);
  48. m_startWait->setSingleShot(true);
  49. m_commandResponseTimer = new QTimer(this);
  50. connect(m_commandResponseTimer, SIGNAL(timeout()), SLOT(_q_commandTimeout()));
  51. m_commandResponseTimer->setSingleShot(true);
  52. m_commandResponseTimer->setInterval(500);
  53. }
  54. SdbConnector::~SdbConnector()
  55. {
  56. }
  57. int SdbConnector::serverPort() const
  58. {
  59. return m_sdbPort;
  60. }
  61. void SdbConnector::setServerPort(int port)
  62. {
  63. m_sdbPort = port;
  64. }
  65. QString SdbConnector::sdbPath() const
  66. {
  67. return m_sdbPath;
  68. }
  69. void SdbConnector::setSdbPath(const QString& path)
  70. {
  71. m_sdbPath = path;
  72. }
  73. SdbState SdbConnector::state() const
  74. {
  75. return m_state;
  76. }
  77. void SdbConnector::startConnector()
  78. {
  79. #ifdef QT_DEBUG
  80. qDebug() << "[SdbConnector::startConnector] State =" << m_state;
  81. #endif
  82. if(m_state == SdbDisconnected || m_state == SdbError) {
  83. startConnecting();
  84. } else if(m_state == SdbDisconnecting) {
  85. m_socket->disconnect(this);
  86. m_socket->deleteLater();
  87. m_socket = NULL;
  88. m_retry = 0;
  89. startConnecting();
  90. }
  91. }
  92. void SdbConnector::stopConnector()
  93. {
  94. #ifdef QT_DEBUG
  95. qDebug() << "[SdbConnector::stopConnector] State =" << m_state;
  96. #endif
  97. m_commandResponseTimer->stop();
  98. if(m_state == SdbConnecting) {
  99. m_socket->disconnect(this);
  100. m_socket->deleteLater();
  101. m_socket = NULL;
  102. m_retry = 0;
  103. m_state = SdbDisconnected;
  104. emit stateChanged(SdbDisconnected);
  105. } else if(m_state == SdbConnected) {
  106. m_socket->disconnectFromHost();
  107. } else if(m_state == SdbDisconnecting) {
  108. } else if(m_state == SdbRestarting) {
  109. m_startWait->stop();
  110. m_retry = 0;
  111. }
  112. }
  113. void SdbConnector::startConnecting()
  114. {
  115. #ifdef QT_DEBUG
  116. qDebug() << "[SdbConnector::startConnecting] Port =" << m_sdbPort;
  117. #endif
  118. if(m_state != SdbConnecting) {
  119. m_state = SdbConnecting;
  120. emit stateChanged(m_state);
  121. }
  122. m_socket = new QTcpSocket(this);
  123. connect(m_socket, SIGNAL(connected()), SLOT(_q_tcpConnected()));
  124. connect(m_socket, SIGNAL(readyRead()), SLOT(_q_readyRead()));
  125. connect(m_socket, SIGNAL(disconnected()), SLOT(_q_tcpDisconnected()));
  126. connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(_q_socketError(QAbstractSocket::SocketError)));
  127. m_socket->connectToHost(QHostAddress::LocalHost, m_sdbPort);
  128. m_commandResponseTimer->start(1000);
  129. }
  130. void SdbConnector::_q_tcpConnected()
  131. {
  132. #ifdef QT_DEBUG
  133. qDebug() << "[SdbConnector::_q_tcpConnected] Local port =" << m_socket->localPort();
  134. #endif
  135. m_commandResponseTimer->stop();
  136. m_state = SdbConnected;
  137. m_protoState = WaitingForDeviceListResp;
  138. m_socket->write(Tizen::SdbPacketUtils::makeRequest(QByteArray("host:track-devices")));
  139. m_commandResponseTimer->start();
  140. emit stateChanged(SdbConnected);
  141. }
  142. void SdbConnector::_q_readyRead()
  143. {
  144. while(!m_socket->atEnd()) {
  145. if(m_protoState == WaitingForDeviceListResp) {
  146. SdbResponse resp;
  147. if(SdbPacketUtils::parseResponse(m_socket, false, resp)) {
  148. m_commandResponseTimer->stop();
  149. m_protoState = WaitingForDeviceListHeader;
  150. if(!resp.okay) {
  151. #ifdef QT_DEBUG
  152. qDebug() << "[SdbConnector] Failed to query device list";
  153. #endif
  154. }
  155. }
  156. }
  157. if(m_protoState == WaitingForDeviceListHeader) {
  158. if(m_socket->bytesAvailable() >= 4) {
  159. char hdr[5];
  160. if(m_socket->read(hdr, 4) != 4)
  161. return;
  162. hdr[4] = 0;
  163. sscanf(hdr, "%X", &m_packetLength);
  164. if(m_packetLength > 0)
  165. m_protoState = WaitingForDeviceListData;
  166. else
  167. continue;
  168. } else {
  169. return;
  170. }
  171. }
  172. if(m_protoState == WaitingForDeviceListData) {
  173. if(m_socket->bytesAvailable() >= m_packetLength) {
  174. SdbDeviceList deviceList;
  175. m_protoState = WaitingForDeviceListHeader;
  176. QByteArray string = m_socket->read(m_packetLength);
  177. QList<QByteArray> lines = string.split('\n');
  178. #ifdef QT_DEBUG
  179. qDebug() << "[SdbConnector]: received list update" << string;
  180. #endif
  181. if(!lines.empty())
  182. deviceList.reserve(lines.size());
  183. foreach(const QByteArray& line, lines) {
  184. QList<QByteArray> params = line.split('\t');
  185. if(params.length() == 3) {
  186. SdbDevice device;
  187. device.serialNumber = params.at(0).trimmed();
  188. device.name = QString::fromUtf8(params.at(2));
  189. QByteArray deviceState = params.at(1);
  190. if(deviceState == "offline") {
  191. device.state = SdbDevice::Offline;
  192. } else if(deviceState == "device") {
  193. device.state = SdbDevice::Device;
  194. } else {
  195. device.state = SdbDevice::Unknown;
  196. }
  197. deviceList.append(device);
  198. }
  199. }
  200. emit deviceListUpdated(deviceList);
  201. } else
  202. return;
  203. }
  204. }
  205. }
  206. void SdbConnector::_q_tcpDisconnected()
  207. {
  208. #ifdef QT_DEBUG
  209. qDebug() << "[SdbConnector::_q_tcpDisconnected]";
  210. #endif
  211. m_commandResponseTimer->stop();
  212. m_socket->disconnect(this);
  213. m_socket->deleteLater();
  214. m_socket = NULL;
  215. m_retry = 0;
  216. m_state = SdbDisconnected;
  217. emit stateChanged(SdbDisconnected);
  218. }
  219. void SdbConnector::_q_socketError(QAbstractSocket::SocketError error)
  220. {
  221. Q_UNUSED(error);
  222. #ifdef QT_DEBUG
  223. qDebug() << "[SdbConnector::_q_socketError] Error =" << error << "and error string =" << m_socket->errorString();
  224. #endif
  225. m_commandResponseTimer->stop();
  226. if(m_state == SdbConnecting) {
  227. m_socket->disconnect(this);
  228. m_socket->deleteLater();
  229. m_socket = NULL;
  230. QFileInfo fi(m_sdbPath);
  231. if(!fi.exists() || m_retry > 0) {
  232. #ifdef QT_DEBUG
  233. qWarning() << "SDB path not found";
  234. #endif
  235. m_state = SdbError;
  236. m_retry = 0;
  237. emit stateChanged(SdbError);
  238. return;
  239. }
  240. m_state = SdbRestarting;
  241. m_sdbProcess = new QProcess(this);
  242. connect(m_sdbProcess, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(_q_finished(int,QProcess::ExitStatus)));
  243. m_sdbProcess->start(m_sdbPath, QStringList() << QLatin1String("start-server"));
  244. emit stateChanged(SdbRestarting);
  245. } else if(m_state == SdbConnected) {
  246. m_socket->disconnect(this);
  247. m_socket->deleteLater();
  248. m_socket = NULL;
  249. m_state = SdbDisconnected;
  250. m_retry = 0;
  251. emit stateChanged(SdbDisconnected);
  252. }
  253. }
  254. void SdbConnector::_q_finished(int exitCode, QProcess::ExitStatus exitStatus)
  255. {
  256. #ifdef QT_DEBUG
  257. qDebug() << "[SdbConnector::_q_finished] Exit code =" << exitCode << "Status =" << exitStatus <<
  258. "Error =" << m_sdbProcess->errorString();
  259. #endif
  260. m_sdbProcess->deleteLater();
  261. m_sdbProcess = NULL;
  262. if(exitStatus == QProcess::NormalExit && exitCode == 0) {
  263. m_startWait->start();
  264. } else {
  265. m_state = SdbError;
  266. m_retry = 0;
  267. emit stateChanged(SdbError);
  268. }
  269. }
  270. void SdbConnector::_q_startWaitTimeout()
  271. {
  272. #ifdef QT_DEBUG
  273. qDebug() << "[SdbConnector::_q_startWaitTimeout]";
  274. #endif
  275. ++m_retry;
  276. startConnecting();
  277. }
  278. QTcpSocket * SdbConnector::createChannel(QObject *parent)
  279. {
  280. if(m_state != SdbConnected)
  281. return NULL;
  282. QTcpSocket * socket = new QTcpSocket(parent);
  283. socket->connectToHost(QHostAddress::LocalHost, m_sdbPort);
  284. return socket;
  285. }
  286. void SdbConnector::_q_commandTimeout()
  287. {
  288. #ifdef QT_DEBUG
  289. qDebug() << "[SdbConnector] Command timeout in state" << m_state;
  290. #endif
  291. if(m_state == SdbConnecting) {
  292. m_socket->disconnect(this);
  293. m_socket->deleteLater();
  294. m_socket = NULL;
  295. QFileInfo fi(m_sdbPath);
  296. if(!fi.exists() || m_retry > 0) {
  297. #ifdef QT_DEBUG
  298. qWarning() << "SDB path not found";
  299. #endif
  300. m_state = SdbError;
  301. m_retry = 0;
  302. emit stateChanged(SdbError);
  303. return;
  304. }
  305. #ifdef QT_DEBUG
  306. qDebug() << "Try starting SDB";
  307. #endif
  308. m_state = SdbRestarting;
  309. m_sdbProcess = new QProcess(this);
  310. connect(m_sdbProcess, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(_q_finished(int,QProcess::ExitStatus)));
  311. m_sdbProcess->start(m_sdbPath, QStringList() << QLatin1String("start-server"));
  312. emit stateChanged(SdbRestarting);
  313. } else if(m_state == SdbConnected) {
  314. m_socket->disconnect(this);
  315. m_socket->deleteLater();
  316. m_socket = NULL;
  317. m_state = SdbError;
  318. m_retry = 0;
  319. emit stateChanged(SdbError);
  320. }
  321. }
  322. }