/qt-everywhere-opensource-src-4.7.1/tools/qtestlib/wince/cetcpsync/qtcesterconnection.cpp
C++ | 552 lines | 493 code | 16 blank | 43 comment | 27 complexity | e05ad907f7b75e56808a9014d71d90c7 MD5 | raw file
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 49extern void debugOutput(const QString& text, int level); 50 51#pragma warning(disable:4996) 52 53#define END_ERROR(s, a) \ 54 if(a) qDebug() << a; \ 55 _freeSocket(s); \ 56 return false; 57 58QtCesterConnection::QtCesterConnection() 59 : AbstractRemoteConnection() 60{ 61} 62 63QtCesterConnection::~QtCesterConnection() 64{ 65} 66 67bool QtCesterConnection::connect(QVariantList&) 68{ 69 // We connect with each command, so this is always true 70 // The command itself will fail then 71 connected = true; 72 return true; 73} 74 75void QtCesterConnection::disconnect() 76{ 77 connected = false; 78} 79 80bool QtCesterConnection::isConnected() const 81{ 82 return connected; 83} 84 85bool QtCesterConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists) 86{ 87 debugOutput( qPrintable(QString::fromLatin1("Copy File: %1 -> %2").arg(localSource).arg(deviceDest)),0); 88 QFile localFile(localSource); 89 QFileInfo info(localSource); 90 if (!localFile.exists() || !localFile.open(QIODevice::ReadOnly)) { 91 qDebug() << "Could not open File!"; 92 return false; 93 } 94 95 QTcpSocket* socket = 0; 96 if (!_initCommand(socket, COMMAND_CREATE_FILE)) { 97 END_ERROR(socket, "Could not initialized command"); 98 } 99 100 CreateFileOptions option; 101 strcpy(option.fileName, qPrintable(deviceDest)); 102#ifdef Q_OS_WIN 103 // Copy FileTime for update verification 104 FILETIME creationTime, accessTime, writeTime; 105 HANDLE localHandle = CreateFile(localSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 106 if (localHandle != INVALID_HANDLE_VALUE) { 107 if (GetFileTime(localHandle, &creationTime, &accessTime, &writeTime)) { 108 LocalFileTimeToFileTime(&writeTime, &writeTime); 109 option.fileTime = writeTime; 110 } 111 CloseHandle(localHandle); 112 } 113 DWORD attributes = GetFileAttributes(localSource.utf16()); 114 if (attributes != -1 ) 115 option.fileAttributes = attributes; 116#endif 117 option.fileSize = info.size(); 118 option.overwriteExisting = !failIfExists; 119 120 if (!_sendData(socket, (char*) &option, sizeof(option))) { 121 END_ERROR(socket, "Could not send options..."); 122 } 123 124 if (!_checkResult(socket)) { 125 END_ERROR(socket, "Server did not accept configuration"); 126 } 127 128 int bytesWritten = 0; 129 const int bufferSize = 1024; 130 QByteArray data; 131 while (bytesWritten < option.fileSize) { 132 data = localFile.read(bufferSize); 133 bytesWritten += data.size(); 134#ifdef Q_OS_WIN 135 wprintf( L"%s -> %s (%d / %d) %d %%\r", localSource.utf16() , deviceDest.utf16(), 136 bytesWritten , option.fileSize, (100*bytesWritten)/option.fileSize ); 137#endif 138 if (!_sendData(socket, data.constData(), data.size())) { 139 END_ERROR(socket, "Error during file transfer"); 140 } 141 if (!_checkResult(socket)) { 142 END_ERROR(socket, "Got some strange result"); 143 } 144 } 145#ifdef Q_OS_WIN 146 wprintf( L"\n"); // We should jump to next line... 147#endif 148 if (bytesWritten != option.fileSize) { 149 END_ERROR(socket, "Did not send sufficient data"); 150 } 151 _freeSocket(socket); 152 return true; 153} 154 155bool QtCesterConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive) 156{ 157 QTcpSocket* socket = NULL; 158 QFileInfo info(localSource); 159 if (!info.exists() || !info.isDir()) { 160 END_ERROR(socket, "Input directory invalid"); 161 } 162 163 createDirectory(deviceDest, true); 164 QDir dir(localSource); 165 QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); 166 foreach(QFileInfo item, list) { 167 QString targetName = deviceDest + QLatin1String("\\") + item.fileName(); 168 if (item.isDir()) { 169 if (recursive) { 170 if (!copyDirectoryToDevice(item.absoluteFilePath() , targetName, recursive)) 171 return false; 172 } 173 } else { 174 if (!copyFileToDevice(item.absoluteFilePath(), targetName)) 175 return false; 176 } 177 } 178 return true; 179} 180 181bool QtCesterConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists) 182{ 183 QFile targetFile(localDest); 184 QTcpSocket* socket = 0; 185 if (targetFile.exists() && failIfExists) { 186 END_ERROR(socket, "Local file not supposed to be overwritten"); 187 } 188 189 if (!targetFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { 190 END_ERROR(socket, "Could not open local file for writing"); 191 } 192 193 if (!_initCommand(socket, COMMAND_READ_FILE)) { 194 END_ERROR(socket, "Could not establish connection"); 195 } 196 197 ReadFileOptions option; 198 strcpy(option.fileName, qPrintable(deviceSource)); 199 if (!_sendData(socket, (char*) &option, sizeof(option))) { 200 END_ERROR(socket, "Could not send options"); 201 } 202 203 QByteArray data; 204 if (!_receiveData(socket, data)) { 205 END_ERROR(socket, "Did not receive any data"); 206 } 207 208 ReadFileReply* reply = (ReadFileReply*) data.data(); 209 if (!reply->fileValid) { 210 END_ERROR(socket, "Requested file invalid"); 211 } 212 213 int fileSize = reply->fileSize; 214 int currentSize = 0; 215 // ### TODO: make a little bit more error-prone 216 do { 217 _sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS)); 218 _receiveData(socket, data); 219 currentSize += data.size(); 220 targetFile.write(data); 221 } while(currentSize < fileSize); 222 223 _freeSocket(socket); 224 targetFile.close(); 225 return true; 226} 227 228bool QtCesterConnection::copyDirectoryFromDevice(const QString& /*deviceSource*/ 229 , const QString& /*localDest*/ 230 , bool /*recursive*/) 231{ 232 qDebug() << "To be implemented!! Should not be needed for autotest system"; 233 exit(-1); 234 return false; 235} 236 237bool QtCesterConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists) 238{ 239 QTcpSocket* socket = 0; 240 if (!_initCommand(socket, COMMAND_COPY_FILE)) { 241 END_ERROR(socket, "Could not establish connection for copy"); 242 } 243 244 CopyFileOptions option; 245 strcpy(option.from, qPrintable(srcFile)); 246 strcpy(option.to, qPrintable(destFile)); 247 option.overwriteExisting = !failIfExists; 248 if (!_sendData(socket, (char*) &option, sizeof(option))) { 249 END_ERROR(socket, "Could not send copy options"); 250 } 251 252 if (!_checkResult(socket)) { 253 END_ERROR(socket, "Copy failed"); 254 } 255 256 _freeSocket(socket); 257 return true; 258} 259 260bool QtCesterConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory, 261 bool recursive) 262{ 263 QTcpSocket* socket = 0; 264 if (!_initCommand(socket, COMMAND_COPY_DIRECTORY)) { 265 END_ERROR(socket, "Could not establish connection for dir copy"); 266 } 267 268 CopyDirectoryOptions option; 269 strcpy(option.from, qPrintable(srcDirectory)); 270 strcpy(option.to, qPrintable(destDirectory)); 271 option.recursive = recursive; 272 if (!_sendData(socket, (char*) &option, sizeof(option))) { 273 END_ERROR(socket, "Could not send dir copy options"); 274 } 275 276 if (!_checkResult(socket)) { 277 END_ERROR(socket, "Dir Copy failed"); 278 } 279 280 _freeSocket(socket); 281 return true; 282} 283 284bool QtCesterConnection::deleteFile(const QString &fileName) 285{ 286 QTcpSocket* socket = 0; 287 if (!_initCommand(socket, COMMAND_DELETE_FILE)) { 288 END_ERROR(socket, "Could not establish connection for file deletion"); 289 } 290 291 DeleteFileOptions option; 292 strcpy(option.fileName, qPrintable(fileName)); 293 if (!_sendData(socket, (char*) &option, sizeof(option))) { 294 END_ERROR(socket, "Could not send file options"); 295 } 296 297 if (!_checkResult(socket)) { 298 //END_ERROR(socket, "File Deletion failed"); 299 // This is actually not an error so ignore it. 300 } 301 302 _freeSocket(socket); 303 return true; 304} 305 306bool QtCesterConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists) 307{ 308 QTcpSocket* socket = 0; 309 if (!_initCommand(socket, COMMAND_DELETE_DIRECTORY)) { 310 END_ERROR(socket, "Could not establish connection for dir deletion"); 311 } 312 313 DeleteDirectoryOptions option; 314 strcpy(option.dirName, qPrintable(directory)); 315 option.recursive = recursive; 316 option.failIfContentExists = failIfContentExists; 317 if (!_sendData(socket, (char*) &option, sizeof(option))) { 318 END_ERROR(socket, "Could not send dir options"); 319 } 320 321 if (!_checkResult(socket)) { 322 // we do not write an error as this will fail a lot on recursive. 323 END_ERROR(socket, 0); 324 } 325 326 _freeSocket(socket); 327 return true; 328} 329 330bool QtCesterConnection::execute(QString program, 331 QString arguments, 332 int timeout, 333 int *returnValue) 334{ 335 QTcpSocket* socket = 0; 336 if (!_initCommand(socket, COMMAND_EXECUTE)) { 337 END_ERROR(socket, "Could not establish connection for dir deletion"); 338 } 339 340 ExecuteOptions options; 341 strcpy(options.appName, qPrintable(program)); 342 QStringList argList = arguments.split(QLatin1Char(' ')); 343 options.argumentsCount = qMin(argList.size(), MAX_ARGUMENTS); 344 options.waitForFinished = true; 345 options.timeout = timeout; 346 if (!_sendData(socket, (char*) &options, sizeof(options))) { 347 END_ERROR(socket, "Could not send dir options"); 348 } 349 if (!_checkResult(socket)) { 350 END_ERROR(socket, "Did not receive an answer"); 351 } 352 353 for (int i=0; i < options.argumentsCount; ++i) { 354 char someData[MAX_NAME_LENGTH]; 355 strcpy(someData, qPrintable(argList[i])); 356 if (!_sendData(socket, someData, MAX_NAME_LENGTH)) { 357 END_ERROR(socket, "Could not send argument"); 358 } 359 if (!_checkResult(socket)) { 360 END_ERROR(socket, "Failure in argument send"); 361 } 362 } 363 364 // trigger the startup 365 if (!_sendData(socket, COMMAND_SUCCESS, strlen(COMMAND_SUCCESS))) { 366 END_ERROR(socket, "Could not trigger startup"); 367 } 368 369 const int waitTime = 60 * 60 * 1000; 370 if (!socket->waitForReadyRead(waitTime)) { 371 END_ERROR(socket, "Process timed out"); 372 } 373 374 QByteArray result = socket->readAll(); 375 if (result != COMMAND_SUCCESS) { 376 if (returnValue) 377 *returnValue = -1; // just some at least 378 END_ERROR(socket, "Application did not start or returned error"); 379 } 380 381 if (returnValue) 382 *returnValue = 0; 383 _freeSocket(socket); 384 return true; 385} 386 387bool QtCesterConnection::createDirectory(const QString &path, bool deleteBefore) 388{ 389 if (deleteBefore) 390 deleteDirectory(path, true, true); 391 392 QTcpSocket* socket = 0; 393 if (!_initCommand(socket, COMMAND_CREATE_DIRECTORY)) { 394 END_ERROR(socket, "Could not establish connection for dir creation"); 395 } 396 397 CreateDirectoryOptions option; 398 strcpy(option.dirName, qPrintable(path)); 399 option.recursively = true; 400 if (!_sendData(socket, (char*) &option, sizeof(option))) { 401 END_ERROR(socket, "Could not send dir options"); 402 } 403 404 if (!_checkResult(socket)) { 405 END_ERROR(socket, "Dir creation failed"); 406 } 407 408 _freeSocket(socket); 409 return true; 410} 411 412bool QtCesterConnection::timeStampForLocalFileTime(FILETIME* fTime) const 413{ 414 if (!fTime) 415 return false; 416 417 FILETIME copyTime = *fTime; 418 LocalFileTimeToFileTime(©Time, ©Time); 419 420 QTcpSocket* socket = 0; 421 if (!_initCommand(socket, COMMAND_TIME_STAMP)) { 422 END_ERROR(socket, "Could not establish time stamp connection"); 423 } 424 425 if (!_sendData(socket, (char*) ©Time, sizeof(copyTime))) { 426 END_ERROR(socket, "Could not send stamp time"); 427 } 428 429 QByteArray data; 430 if (!_receiveData(socket, data)) { 431 END_ERROR(socket, "Did not receive time stamp or connection interrupted"); 432 } 433 434 copyTime = *((FILETIME*)data.data()); 435 if (copyTime.dwLowDateTime == -1 && copyTime.dwHighDateTime == -1) { 436 END_ERROR(socket, "remote Time stamp failed!"); 437 } 438 439 *fTime = copyTime; 440 _freeSocket(socket); 441 return true; 442} 443 444bool QtCesterConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const 445{ 446 if (!deviceCreationTime) 447 return false; 448 449 QTcpSocket* socket = 0; 450 if (!_initCommand(socket, COMMAND_FILE_TIME)) { 451 END_ERROR(socket, "Could not establish connection for file time access"); 452 } 453 454 FileTimeOptions option; 455 strcpy(option.fileName, qPrintable(fileName)); 456 if (!_sendData(socket, (char*) &option, sizeof(option))) { 457 END_ERROR(socket, "Could not send file time name"); 458 } 459 460 QByteArray data; 461 if (!_receiveData(socket, data)) { 462 END_ERROR(socket, "File Time request failed"); 463 } 464 465 FILETIME* resultTime = (FILETIME*) data.data(); 466 if (resultTime->dwLowDateTime == -1 && resultTime->dwHighDateTime == -1) { 467 END_ERROR(socket, 0); 468 debugOutput("Could not access file time", 0); 469 } 470 471 *deviceCreationTime = *resultTime; 472 _freeSocket(socket); 473 return true; 474} 475 476bool QtCesterConnection::_createSocket(QTcpSocket*& result) const 477{ 478 QTcpSocket* sock = new QTcpSocket(); 479 QByteArray ipAddress = qgetenv("DEVICE_IP"); 480 if (ipAddress.isEmpty()) { 481 qWarning("Error: You need to have DEVICE_IP set"); 482 exit(0); 483 } 484 sock->connectToHost(QHostAddress(QString(ipAddress)), 12145); 485 486 if (!sock->waitForConnected()) { 487 qDebug() << "connection timeout..."; 488 result = NULL; 489 return false; 490 } 491 result = sock; 492 return true; 493} 494 495void QtCesterConnection::_freeSocket(QTcpSocket*& sock) const 496{ 497 if (!sock) 498 return; 499 if (sock->state() == QAbstractSocket::ConnectedState) { 500 sock->disconnectFromHost(); 501 // seems like no need to wait 502 //sock->waitForDisconnected(); 503 } 504 delete sock; 505 sock = NULL; 506#ifdef Q_OS_WIN 507 Sleep(100); 508#endif 509} 510 511bool QtCesterConnection::_initCommand(QTcpSocket*& sock, const char* command) const 512{ 513 QTcpSocket* socket = NULL; 514 if (!_createSocket(socket)) { 515 END_ERROR(socket, "Could not connect to server"); 516 } 517 518 if (!_sendData(socket, command, strlen(command)) || 519 !_checkResult(socket)) { 520 END_ERROR(socket, "Cound not send command"); 521 } 522 sock = socket; 523 return true; 524} 525 526bool QtCesterConnection::_sendData(QTcpSocket*& sock, const char* data, int dataSize) const 527{ 528 int amount = sock->write(data, dataSize); 529 if (amount != dataSize) { 530 fprintf(stderr, "*******COULD NOT SEND ENOUGH DATA*************\n"); 531 } 532 return sock->waitForBytesWritten(); 533} 534 535bool QtCesterConnection::_receiveData(QTcpSocket*& sock, QByteArray& data) const 536{ 537 if (!sock->waitForReadyRead()) { 538 qDebug() << "did not receive any data"; 539 return false; 540 } 541 data = sock->readAll(); 542 return true; 543} 544 545bool QtCesterConnection::_checkResult(QTcpSocket*& sock) const 546{ 547 QByteArray response; 548 if (!_receiveData(sock, response) || response != COMMAND_SUCCESS) 549 return false; 550 return true; 551} 552