PageRenderTime 82ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/qt-everywhere-opensource-src-4.7.1/tools/qtestlib/wince/cetcpsync/qtcesterconnection.cpp

https://bitbucket.org/boroondas/3p-qt-open-83
C++ | 552 lines | 493 code | 16 blank | 43 comment | 27 complexity | e05ad907f7b75e56808a9014d71d90c7 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, GPL-3.0, CC-BY-SA-4.0, Apache-2.0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the tools applications of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** Commercial Usage
  11. ** Licensees holding valid Qt Commercial licenses may use this file in
  12. ** accordance with the Qt Commercial License Agreement provided with the
  13. ** Software or, alternatively, in accordance with the terms contained in
  14. ** a written agreement between you and Nokia.
  15. **
  16. ** GNU Lesser General Public License Usage
  17. ** Alternatively, this file may be used under the terms of the GNU Lesser
  18. ** General Public License version 2.1 as published by the Free Software
  19. ** Foundation and appearing in the file LICENSE.LGPL included in the
  20. ** packaging of this file. Please review the following information to
  21. ** ensure the GNU Lesser General Public License version 2.1 requirements
  22. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  23. **
  24. ** In addition, as a special exception, Nokia gives you certain additional
  25. ** rights. These rights are described in the Nokia Qt LGPL Exception
  26. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  27. **
  28. ** GNU General Public License Usage
  29. ** Alternatively, this file may be used under the terms of the GNU
  30. ** General Public License version 3.0 as published by the Free Software
  31. ** Foundation and appearing in the file LICENSE.GPL included in the
  32. ** packaging of this file. Please review the following information to
  33. ** ensure the GNU General Public License version 3.0 requirements will be
  34. ** met: http://www.gnu.org/copyleft/gpl.html.
  35. **
  36. ** If you have questions regarding the use of this file, please contact
  37. ** Nokia at qt-info@nokia.com.
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qtcesterconnection.h"
  42. #include <transfer_global.h>
  43. #include <QtCore/QDir>
  44. #include <QtCore/QFile>
  45. #include <QtCore/QFileInfo>
  46. #include <QtNetwork/QTcpSocket>
  47. #include <QtNetwork/QHostAddress>
  48. extern void debugOutput(const QString& text, int level);
  49. #pragma warning(disable:4996)
  50. #define END_ERROR(s, a) \
  51. if(a) qDebug() << a; \
  52. _freeSocket(s); \
  53. return false;
  54. QtCesterConnection::QtCesterConnection()
  55. : AbstractRemoteConnection()
  56. {
  57. }
  58. QtCesterConnection::~QtCesterConnection()
  59. {
  60. }
  61. bool QtCesterConnection::connect(QVariantList&)
  62. {
  63. // We connect with each command, so this is always true
  64. // The command itself will fail then
  65. connected = true;
  66. return true;
  67. }
  68. void QtCesterConnection::disconnect()
  69. {
  70. connected = false;
  71. }
  72. bool QtCesterConnection::isConnected() const
  73. {
  74. return connected;
  75. }
  76. bool QtCesterConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists)
  77. {
  78. debugOutput( qPrintable(QString::fromLatin1("Copy File: %1 -> %2").arg(localSource).arg(deviceDest)),0);
  79. QFile localFile(localSource);
  80. QFileInfo info(localSource);
  81. if (!localFile.exists() || !localFile.open(QIODevice::ReadOnly)) {
  82. qDebug() << "Could not open File!";
  83. return false;
  84. }
  85. QTcpSocket* socket = 0;
  86. if (!_initCommand(socket, COMMAND_CREATE_FILE)) {
  87. END_ERROR(socket, "Could not initialized command");
  88. }
  89. CreateFileOptions option;
  90. strcpy(option.fileName, qPrintable(deviceDest));
  91. #ifdef Q_OS_WIN
  92. // Copy FileTime for update verification
  93. FILETIME creationTime, accessTime, writeTime;
  94. HANDLE localHandle = CreateFile(localSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
  95. if (localHandle != INVALID_HANDLE_VALUE) {
  96. if (GetFileTime(localHandle, &creationTime, &accessTime, &writeTime)) {
  97. LocalFileTimeToFileTime(&writeTime, &writeTime);
  98. option.fileTime = writeTime;
  99. }
  100. CloseHandle(localHandle);
  101. }
  102. DWORD attributes = GetFileAttributes(localSource.utf16());
  103. if (attributes != -1 )
  104. option.fileAttributes = attributes;
  105. #endif
  106. option.fileSize = info.size();
  107. option.overwriteExisting = !failIfExists;
  108. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  109. END_ERROR(socket, "Could not send options...");
  110. }
  111. if (!_checkResult(socket)) {
  112. END_ERROR(socket, "Server did not accept configuration");
  113. }
  114. int bytesWritten = 0;
  115. const int bufferSize = 1024;
  116. QByteArray data;
  117. while (bytesWritten < option.fileSize) {
  118. data = localFile.read(bufferSize);
  119. bytesWritten += data.size();
  120. #ifdef Q_OS_WIN
  121. wprintf( L"%s -> %s (%d / %d) %d %%\r", localSource.utf16() , deviceDest.utf16(),
  122. bytesWritten , option.fileSize, (100*bytesWritten)/option.fileSize );
  123. #endif
  124. if (!_sendData(socket, data.constData(), data.size())) {
  125. END_ERROR(socket, "Error during file transfer");
  126. }
  127. if (!_checkResult(socket)) {
  128. END_ERROR(socket, "Got some strange result");
  129. }
  130. }
  131. #ifdef Q_OS_WIN
  132. wprintf( L"\n"); // We should jump to next line...
  133. #endif
  134. if (bytesWritten != option.fileSize) {
  135. END_ERROR(socket, "Did not send sufficient data");
  136. }
  137. _freeSocket(socket);
  138. return true;
  139. }
  140. bool QtCesterConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive)
  141. {
  142. QTcpSocket* socket = NULL;
  143. QFileInfo info(localSource);
  144. if (!info.exists() || !info.isDir()) {
  145. END_ERROR(socket, "Input directory invalid");
  146. }
  147. createDirectory(deviceDest, true);
  148. QDir dir(localSource);
  149. QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
  150. foreach(QFileInfo item, list) {
  151. QString targetName = deviceDest + QLatin1String("\\") + item.fileName();
  152. if (item.isDir()) {
  153. if (recursive) {
  154. if (!copyDirectoryToDevice(item.absoluteFilePath() , targetName, recursive))
  155. return false;
  156. }
  157. } else {
  158. if (!copyFileToDevice(item.absoluteFilePath(), targetName))
  159. return false;
  160. }
  161. }
  162. return true;
  163. }
  164. bool QtCesterConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists)
  165. {
  166. QFile targetFile(localDest);
  167. QTcpSocket* socket = 0;
  168. if (targetFile.exists() && failIfExists) {
  169. END_ERROR(socket, "Local file not supposed to be overwritten");
  170. }
  171. if (!targetFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
  172. END_ERROR(socket, "Could not open local file for writing");
  173. }
  174. if (!_initCommand(socket, COMMAND_READ_FILE)) {
  175. END_ERROR(socket, "Could not establish connection");
  176. }
  177. ReadFileOptions option;
  178. strcpy(option.fileName, qPrintable(deviceSource));
  179. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  180. END_ERROR(socket, "Could not send options");
  181. }
  182. QByteArray data;
  183. if (!_receiveData(socket, data)) {
  184. END_ERROR(socket, "Did not receive any data");
  185. }
  186. ReadFileReply* reply = (ReadFileReply*) data.data();
  187. if (!reply->fileValid) {
  188. END_ERROR(socket, "Requested file invalid");
  189. }
  190. int fileSize = reply->fileSize;
  191. int currentSize = 0;
  192. // ### TODO: make a little bit more error-prone
  193. do {
  194. _sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS));
  195. _receiveData(socket, data);
  196. currentSize += data.size();
  197. targetFile.write(data);
  198. } while(currentSize < fileSize);
  199. _freeSocket(socket);
  200. targetFile.close();
  201. return true;
  202. }
  203. bool QtCesterConnection::copyDirectoryFromDevice(const QString& /*deviceSource*/
  204. , const QString& /*localDest*/
  205. , bool /*recursive*/)
  206. {
  207. qDebug() << "To be implemented!! Should not be needed for autotest system";
  208. exit(-1);
  209. return false;
  210. }
  211. bool QtCesterConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists)
  212. {
  213. QTcpSocket* socket = 0;
  214. if (!_initCommand(socket, COMMAND_COPY_FILE)) {
  215. END_ERROR(socket, "Could not establish connection for copy");
  216. }
  217. CopyFileOptions option;
  218. strcpy(option.from, qPrintable(srcFile));
  219. strcpy(option.to, qPrintable(destFile));
  220. option.overwriteExisting = !failIfExists;
  221. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  222. END_ERROR(socket, "Could not send copy options");
  223. }
  224. if (!_checkResult(socket)) {
  225. END_ERROR(socket, "Copy failed");
  226. }
  227. _freeSocket(socket);
  228. return true;
  229. }
  230. bool QtCesterConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory,
  231. bool recursive)
  232. {
  233. QTcpSocket* socket = 0;
  234. if (!_initCommand(socket, COMMAND_COPY_DIRECTORY)) {
  235. END_ERROR(socket, "Could not establish connection for dir copy");
  236. }
  237. CopyDirectoryOptions option;
  238. strcpy(option.from, qPrintable(srcDirectory));
  239. strcpy(option.to, qPrintable(destDirectory));
  240. option.recursive = recursive;
  241. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  242. END_ERROR(socket, "Could not send dir copy options");
  243. }
  244. if (!_checkResult(socket)) {
  245. END_ERROR(socket, "Dir Copy failed");
  246. }
  247. _freeSocket(socket);
  248. return true;
  249. }
  250. bool QtCesterConnection::deleteFile(const QString &fileName)
  251. {
  252. QTcpSocket* socket = 0;
  253. if (!_initCommand(socket, COMMAND_DELETE_FILE)) {
  254. END_ERROR(socket, "Could not establish connection for file deletion");
  255. }
  256. DeleteFileOptions option;
  257. strcpy(option.fileName, qPrintable(fileName));
  258. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  259. END_ERROR(socket, "Could not send file options");
  260. }
  261. if (!_checkResult(socket)) {
  262. //END_ERROR(socket, "File Deletion failed");
  263. // This is actually not an error so ignore it.
  264. }
  265. _freeSocket(socket);
  266. return true;
  267. }
  268. bool QtCesterConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists)
  269. {
  270. QTcpSocket* socket = 0;
  271. if (!_initCommand(socket, COMMAND_DELETE_DIRECTORY)) {
  272. END_ERROR(socket, "Could not establish connection for dir deletion");
  273. }
  274. DeleteDirectoryOptions option;
  275. strcpy(option.dirName, qPrintable(directory));
  276. option.recursive = recursive;
  277. option.failIfContentExists = failIfContentExists;
  278. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  279. END_ERROR(socket, "Could not send dir options");
  280. }
  281. if (!_checkResult(socket)) {
  282. // we do not write an error as this will fail a lot on recursive.
  283. END_ERROR(socket, 0);
  284. }
  285. _freeSocket(socket);
  286. return true;
  287. }
  288. bool QtCesterConnection::execute(QString program,
  289. QString arguments,
  290. int timeout,
  291. int *returnValue)
  292. {
  293. QTcpSocket* socket = 0;
  294. if (!_initCommand(socket, COMMAND_EXECUTE)) {
  295. END_ERROR(socket, "Could not establish connection for dir deletion");
  296. }
  297. ExecuteOptions options;
  298. strcpy(options.appName, qPrintable(program));
  299. QStringList argList = arguments.split(QLatin1Char(' '));
  300. options.argumentsCount = qMin(argList.size(), MAX_ARGUMENTS);
  301. options.waitForFinished = true;
  302. options.timeout = timeout;
  303. if (!_sendData(socket, (char*) &options, sizeof(options))) {
  304. END_ERROR(socket, "Could not send dir options");
  305. }
  306. if (!_checkResult(socket)) {
  307. END_ERROR(socket, "Did not receive an answer");
  308. }
  309. for (int i=0; i < options.argumentsCount; ++i) {
  310. char someData[MAX_NAME_LENGTH];
  311. strcpy(someData, qPrintable(argList[i]));
  312. if (!_sendData(socket, someData, MAX_NAME_LENGTH)) {
  313. END_ERROR(socket, "Could not send argument");
  314. }
  315. if (!_checkResult(socket)) {
  316. END_ERROR(socket, "Failure in argument send");
  317. }
  318. }
  319. // trigger the startup
  320. if (!_sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS))) {
  321. END_ERROR(socket, "Could not trigger startup");
  322. }
  323. const int waitTime = 60 * 60 * 1000;
  324. if (!socket->waitForReadyRead(waitTime)) {
  325. END_ERROR(socket, "Process timed out");
  326. }
  327. QByteArray result = socket->readAll();
  328. if (result != COMMAND_SUCCESS) {
  329. if (returnValue)
  330. *returnValue = -1; // just some at least
  331. END_ERROR(socket, "Application did not start or returned error");
  332. }
  333. if (returnValue)
  334. *returnValue = 0;
  335. _freeSocket(socket);
  336. return true;
  337. }
  338. bool QtCesterConnection::createDirectory(const QString &path, bool deleteBefore)
  339. {
  340. if (deleteBefore)
  341. deleteDirectory(path, true, true);
  342. QTcpSocket* socket = 0;
  343. if (!_initCommand(socket, COMMAND_CREATE_DIRECTORY)) {
  344. END_ERROR(socket, "Could not establish connection for dir creation");
  345. }
  346. CreateDirectoryOptions option;
  347. strcpy(option.dirName, qPrintable(path));
  348. option.recursively = true;
  349. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  350. END_ERROR(socket, "Could not send dir options");
  351. }
  352. if (!_checkResult(socket)) {
  353. END_ERROR(socket, "Dir creation failed");
  354. }
  355. _freeSocket(socket);
  356. return true;
  357. }
  358. bool QtCesterConnection::timeStampForLocalFileTime(FILETIME* fTime) const
  359. {
  360. if (!fTime)
  361. return false;
  362. FILETIME copyTime = *fTime;
  363. LocalFileTimeToFileTime(&copyTime, &copyTime);
  364. QTcpSocket* socket = 0;
  365. if (!_initCommand(socket, COMMAND_TIME_STAMP)) {
  366. END_ERROR(socket, "Could not establish time stamp connection");
  367. }
  368. if (!_sendData(socket, (char*) &copyTime, sizeof(copyTime))) {
  369. END_ERROR(socket, "Could not send stamp time");
  370. }
  371. QByteArray data;
  372. if (!_receiveData(socket, data)) {
  373. END_ERROR(socket, "Did not receive time stamp or connection interrupted");
  374. }
  375. copyTime = *((FILETIME*)data.data());
  376. if (copyTime.dwLowDateTime == -1 && copyTime.dwHighDateTime == -1) {
  377. END_ERROR(socket, "remote Time stamp failed!");
  378. }
  379. *fTime = copyTime;
  380. _freeSocket(socket);
  381. return true;
  382. }
  383. bool QtCesterConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const
  384. {
  385. if (!deviceCreationTime)
  386. return false;
  387. QTcpSocket* socket = 0;
  388. if (!_initCommand(socket, COMMAND_FILE_TIME)) {
  389. END_ERROR(socket, "Could not establish connection for file time access");
  390. }
  391. FileTimeOptions option;
  392. strcpy(option.fileName, qPrintable(fileName));
  393. if (!_sendData(socket, (char*) &option, sizeof(option))) {
  394. END_ERROR(socket, "Could not send file time name");
  395. }
  396. QByteArray data;
  397. if (!_receiveData(socket, data)) {
  398. END_ERROR(socket, "File Time request failed");
  399. }
  400. FILETIME* resultTime = (FILETIME*) data.data();
  401. if (resultTime->dwLowDateTime == -1 && resultTime->dwHighDateTime == -1) {
  402. END_ERROR(socket, 0);
  403. debugOutput("Could not access file time", 0);
  404. }
  405. *deviceCreationTime = *resultTime;
  406. _freeSocket(socket);
  407. return true;
  408. }
  409. bool QtCesterConnection::_createSocket(QTcpSocket*& result) const
  410. {
  411. QTcpSocket* sock = new QTcpSocket();
  412. QByteArray ipAddress = qgetenv("DEVICE_IP");
  413. if (ipAddress.isEmpty()) {
  414. qWarning("Error: You need to have DEVICE_IP set");
  415. exit(0);
  416. }
  417. sock->connectToHost(QHostAddress(QString(ipAddress)), 12145);
  418. if (!sock->waitForConnected()) {
  419. qDebug() << "connection timeout...";
  420. result = NULL;
  421. return false;
  422. }
  423. result = sock;
  424. return true;
  425. }
  426. void QtCesterConnection::_freeSocket(QTcpSocket*& sock) const
  427. {
  428. if (!sock)
  429. return;
  430. if (sock->state() == QAbstractSocket::ConnectedState) {
  431. sock->disconnectFromHost();
  432. // seems like no need to wait
  433. //sock->waitForDisconnected();
  434. }
  435. delete sock;
  436. sock = NULL;
  437. #ifdef Q_OS_WIN
  438. Sleep(100);
  439. #endif
  440. }
  441. bool QtCesterConnection::_initCommand(QTcpSocket*& sock, const char* command) const
  442. {
  443. QTcpSocket* socket = NULL;
  444. if (!_createSocket(socket)) {
  445. END_ERROR(socket, "Could not connect to server");
  446. }
  447. if (!_sendData(socket, command, strlen(command)) ||
  448. !_checkResult(socket)) {
  449. END_ERROR(socket, "Cound not send command");
  450. }
  451. sock = socket;
  452. return true;
  453. }
  454. bool QtCesterConnection::_sendData(QTcpSocket*& sock, const char* data, int dataSize) const
  455. {
  456. int amount = sock->write(data, dataSize);
  457. if (amount != dataSize) {
  458. fprintf(stderr, "*******COULD NOT SEND ENOUGH DATA*************\n");
  459. }
  460. return sock->waitForBytesWritten();
  461. }
  462. bool QtCesterConnection::_receiveData(QTcpSocket*& sock, QByteArray& data) const
  463. {
  464. if (!sock->waitForReadyRead()) {
  465. qDebug() << "did not receive any data";
  466. return false;
  467. }
  468. data = sock->readAll();
  469. return true;
  470. }
  471. bool QtCesterConnection::_checkResult(QTcpSocket*& sock) const
  472. {
  473. QByteArray response;
  474. if (!_receiveData(sock, response) || response != COMMAND_SUCCESS)
  475. return false;
  476. return true;
  477. }