I have a UI app in C++ and QT5.4, Im using CryptoPP 5.6.2 to encrypt files. I ran into the following problem:
When the Encrypt button is hit, a new thread is started based on this tutorial.
// new thread
CryptoWorkerThread = new QThread;
this->worker = new CryptoWorker(fileName.c_str(), newFileName.c_str(), key, keyLength, iv);
this->worker->moveToThread(CryptoWorkerThread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(CryptoWorkerThread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), CryptoWorkerThread, SLOT(quit()));
connect(worker, SIGNAL(finished()), this, SLOT(on_CryptoWorker_finished()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(CryptoWorkerThread, SIGNAL(finished()), CryptoWorkerThread, SLOT(deleteLater()));
CryptoWorkerThread->start();
I store pointer to the thread and worker in the mainwindow class (parent of the encrypt button and thus the slot)
Worker Class:
class CryptoWorker : public QObject {
Q_OBJECT
public:
CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv);
~CryptoWorker();
const char* sourceFileName;
const char* destFileName;
public slots:
void process();
signals:
void finished();
void error(QString err);
private:
// add your variables here
const byte* key;
const byte* iv;
int keyLength;
};
CryptoWorker::CryptoWorker(const char* sourceFileName, const char* destFileName, const byte * key, int keyLength, const byte * iv){
this->sourceFileName = sourceFileName;
this->destFileName = destFileName;
this->key = key;
this->keyLength = keyLength;
this->iv = iv;
}
CryptoWorker::~CryptoWorker(){
}
void CryptoWorker::process(){
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, keyLength, iv);
CryptoPP::FileSource(sourceFileName, true,
new CryptoPP::StreamTransformationFilter(
encryptor,
new CryptoPP::FileSink(destFileName),
CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
),
true // StreamTransformationFilter
); // FileSource
emit finished();
return;
}
Now, when the thread is run and I am encrypting file A to file B on the fly, using this function:
CryptoPP::FileSource(sourceFileName, true,
new CryptoPP::StreamTransformationFilter(
encryptor,
new CryptoPP::FileSink(destFileName),
CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING
),
true // StreamTransformationFilter
); // FileSource
But, the thread is stuck until the file finishes encoding and writing, which can take few minutes. I have no way to kill the thread, as there is no place to put an isAlive()
check.
I am trying to find a solution that will allow me to use FileSource, FileSink (speed compared to fstream or file or qfile is amazing) and also let me cancel the operation at some point.
I solved progress monitoring by adding another thread that checks size of the new being created encrypted file B, but it would be cool to have control over the bytes that are being written at a given moment (so that I can check isAlive()
and increment data counters).
At this point I am stuck and cannot find a solution. Please help.
You could try passing false
to second parameter (pumpAll
) of FileSource
constructor and doing the work in a loop in chunks using Pump
method - this should allow to check isAlive
and increment the counters.