PageRenderTime 122ms CodeModel.GetById 46ms app.highlight 71ms 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
  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(&copyTime, &copyTime);
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*) &copyTime, 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