summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/Config.cpp33
-rw-r--r--client/Config.h28
-rw-r--r--client/DownloadClient.cpp110
-rw-r--r--client/DownloadClient.h95
-rw-r--r--client/FileOpThread.cpp63
-rw-r--r--client/FileOpThread.h25
-rw-r--r--client/ProxyClientApp.cpp8
-rw-r--r--client/ProxyClientApp.h3
-rw-r--r--client/SslClient.cpp31
-rw-r--r--client/SslClient.h19
-rw-r--r--client/UpdatedConfig.cpp12
-rw-r--r--client/UpdatedConfig.h5
-rw-r--r--client/client.pro8
13 files changed, 411 insertions, 29 deletions
diff --git a/client/Config.cpp b/client/Config.cpp
index ba62ee0..21b2c44 100644
--- a/client/Config.cpp
+++ b/client/Config.cpp
@@ -44,10 +44,11 @@ void Config::FirewallEntry::Parse(string entry)
/*
* FileEntry nested class section
*/
-void Config::FileEntry::Parse(string entry, ActionType action)
+void Config::FileEntry::Parse(string entry, ActionType _action)
{
Logger::Trace("Parsing file action %s\n", entry.c_str());
+ action = _action;
size_t start = 0, end = 0;
if (action == DeleteAction)
{
@@ -66,8 +67,6 @@ void Config::FileEntry::Parse(string entry, ActionType action)
{
Logger::Error("Unknown FileEntry action!\n");
}
-
- Logger::Debug("path: %s, md5: %s\n", path.c_str(), md5.c_str());
}
@@ -238,6 +237,30 @@ unsigned Config::GetStaticProxyGuiLines()
return maxLine;
}
+vector<Config::FileEntry> Config::GetDeleteList()
+{
+ vector<FileEntry> delLst;
+ for (unsigned i = 0; i < fileActions.size(); i++)
+ {
+ if (fileActions[i].action == FileEntry::DeleteAction)
+ delLst.push_back(fileActions[i]);
+ }
+
+ return delLst;
+}
+
+vector<Config::FileEntry> Config::GetDownloadList()
+{
+ vector<FileEntry> downloadLst;
+ for (unsigned i = 0; i < fileActions.size(); i++)
+ {
+ if (fileActions[i].action == FileEntry::DownloadAction)
+ downloadLst.push_back(fileActions[i]);
+ }
+
+ return downloadLst;
+}
+
void Config::ParseConfig(string data)
{
@@ -366,9 +389,7 @@ void Config::ParseFirewalls(string data)
}
void Config::ParseDeleteList(string data)
-{
- Logger::Debug("Delete list:\n%s", data.c_str());
-
+{
//delete all entries with DeleteAction
for (unsigned i = 0; i < fileActions.size(); i++)
{
diff --git a/client/Config.h b/client/Config.h
index 2392898..466f93a 100644
--- a/client/Config.h
+++ b/client/Config.h
@@ -86,7 +86,7 @@ public:
/**
* @brief Extract and set instance variables from config line
*/
- void Parse(string entry, ActionType action);
+ void Parse(string entry, ActionType _action);
};
/**
@@ -127,14 +127,6 @@ public:
void AcquireConfig();
/**
- * @brief Check whether current confguration is valid <br/>
- * It may become invalid in case if server is not reachable.
- * So every time you want to access Config members or methods you should check this value
- * @return true if configuration is valid and false otherwise
- */
- bool IsConfigValid();
-
- /**
* @brief Get list of country names where at least one proxy available<br/>
* (generic proxy records only)
* @return Alphabetically sorted vector<string> with unique country names
@@ -200,9 +192,21 @@ public:
unsigned GetStaticProxyGuiLines();
/**
- * Static proxy speed value limit.<br/>
- * This value is used to determine speed label color.
- * All speed value below this constant will be red, higher values will be green
+ * @brief Get list of files to be deleted
+ * @return List of FileEntry wrapper object that describe files that should be deleted
+ */
+ vector<FileEntry> GetDeleteList();
+
+ /**
+ * @brief Get list of files to be downloaded
+ * @return List of FileEntry wrapper object that describe files that should be downloaded
+ */
+ vector<FileEntry> GetDownloadList();
+
+ /**
+ * @brief Static proxy speed value limit.<br/>
+ * This value is used to determine speed label color.
+ * All speed value below this constant will be red, higher values will be green
*/
const unsigned StaticProxySpeedLow;
protected:
diff --git a/client/DownloadClient.cpp b/client/DownloadClient.cpp
new file mode 100644
index 0000000..df4da25
--- /dev/null
+++ b/client/DownloadClient.cpp
@@ -0,0 +1,110 @@
+
+#include <QtCore>
+#include "DownloadClient.h"
+
+
+DownloadClient::DownloadClient(): isDownloading(false), current(NULL), currentId(-1)
+{
+ connect(this, SIGNAL(ReplyRecieved(SslClient::RequestType&, QByteArray&)),
+ this, SLOT(FileDataRecieved(SslClient::RequestType&, QByteArray&)));
+}
+
+DownloadClient::DownloadClient(QString addr): SslClient(addr), isDownloading(false), current(NULL), currentId(-1)
+{
+ DownloadClient();
+}
+
+void DownloadClient::Download(const string &filename)
+{
+ pair<string, string> file(filename, 0);
+ vector<pair<string, string> > fileList;
+ fileList.push_back(file);
+ Download(fileList);
+}
+
+void DownloadClient::Download(const pair<string, string> &file)
+{
+ vector<pair<string, string> > fileList;
+ fileList.push_back(file);
+ Download(fileList);
+}
+
+void DownloadClient::Download(const vector<pair<string, string> > &fileList)
+{
+ if (server.isEmpty())
+ {
+ Logger::Error("Server address isn't set! Aborting.\n");
+ return;
+ }
+ if (isDownloading)
+ {
+ Logger::Error("Previous downloading process wasn't finished! Aborting.\n");
+ return;
+ }
+ isDownloading = true;
+ files = fileList;
+ DoDownload();
+}
+
+void DownloadClient::FileDataRecieved(SslClient::RequestType &type, QByteArray &data)
+{
+ if (type != RegularFile)
+ {
+ Logger::Error("Invalid reply recieved: %x\n", type);
+ return;
+ }
+
+ if ((current != NULL) && (current->isOpen()))
+ {
+ Logger::Error("File is not open or invalid state\n");
+ return;
+ }
+
+ pair<string, string> file = files[currentId];
+ string filename = file.first;
+ if (data.size() == FRAGMENT_SIZE)
+ {
+ Logger::Debug("data:\n %s", data.constData());
+ current->write(data);
+ SendFileRequest(filename);
+ }
+ else
+ {
+ if (data.size() != 0)
+ {
+ Logger::Debug("data:\n %s", data.constData());
+ current->write(data);
+ }
+ current->close();
+ delete current;
+ current = NULL;
+
+ /**
+ * @todo md5 hash check
+ */
+
+ DoDownload();
+ }
+}
+
+void DownloadClient::DoDownload()
+{
+ if (currentId < (int)files.size())
+ {
+ currentId++;
+ pair<string, string> file = files[currentId];
+ QString filename = QString::fromLocal8Bit(file.first.c_str());
+ string md5 = file.second;
+ current = new QFile(filename);
+ current->open(QIODevice::ReadWrite);
+
+ Logger::Info("Downloading file %s\n", file.first.c_str());
+ SendFileRequest(file.first);
+ }
+ else
+ {
+ Logger::Info("All files have been downloaded.");
+ isDownloading = false;
+ emit downloadFinished();
+ }
+}
diff --git a/client/DownloadClient.h b/client/DownloadClient.h
new file mode 100644
index 0000000..5b75c2c
--- /dev/null
+++ b/client/DownloadClient.h
@@ -0,0 +1,95 @@
+
+
+#ifndef DOWNLOAD_CLIENT_H
+#define DOWNLOAD_CLIENT_H
+
+#include <string>
+#include <vector>
+#include <QObject>
+#include "SslClient.h"
+
+using std::pair;
+using std::string;
+using std::vector;
+
+class QFile;
+
+class DownloadClient: public SslClient
+{
+Q_OBJECT
+
+public:
+ /**
+ * @brief Initialize new DownloadClient instance
+ */
+ DownloadClient();
+
+ /**
+ * @brief Initialize new DownloadClient instance
+ * @param addr server address or hostname to connect to
+ */
+ DownloadClient(QString addr);
+
+ /**
+ * @brief Download file from server
+ * @param file file path on client machine
+ */
+ void Download(const string &file);
+
+ /**
+ * @brief Download file from server
+ * @param file pair of file name and it's md5 hash value
+ */
+ void Download(const pair<string, string> &file);
+
+ /**
+ * @brief Download list of files
+ * @param files associative array of file names and it's md5 hashes
+ * @note this is designated method among all
+ * @todo It seems that std::map isn't best choice for this purpose
+ * it's quite unsuitable to iterate through(
+ */
+ void Download(const vector<pair<string, string> > &files);
+
+signals:
+ /**
+ * @brief This signal is emitted when all files have been downloaded
+ */
+ void downloadFinished();
+
+private slots:
+ void FileDataRecieved(SslClient::RequestType &type, QByteArray &confdata);
+
+private:
+ /**
+ * @brief size of file data fragment
+ */
+ static const int FRAGMENT_SIZE = 4096;
+
+ /**
+ * @brief indicates that program is downloading file(s) right now
+ */
+ bool isDownloading;
+
+ /**
+ * @brief name of file that is being downloaded
+ */
+ QFile *current;
+
+ /**
+ * @brief index of file that is being downloaded
+ */
+ int currentId;
+
+ /**
+ * @brief List of file to
+ */
+ vector<pair<string, string> > files;
+
+ /**
+ * @brief start file-by-file downloading process
+ */
+ void DoDownload();
+};
+
+#endif
diff --git a/client/FileOpThread.cpp b/client/FileOpThread.cpp
new file mode 100644
index 0000000..42cb51b
--- /dev/null
+++ b/client/FileOpThread.cpp
@@ -0,0 +1,63 @@
+
+#include <QtCore>
+#include "DownloadClient.h"
+#include "FileOpThread.h"
+#include "UpdatedConfig.h"
+
+void FileOpThread::run()
+{
+ UpdatedConfig *cfg = UpdatedConfig::CurrentConfig();
+
+ /* delete files */
+ vector<Config::FileEntry> toDelete = cfg->GetDeleteList();
+ for (unsigned i = 0; i < toDelete.size(); i++)
+ {
+ Logger::Trace("Deleting file: \"%s\"\n", toDelete[i].path.c_str());
+
+ QString path = QString::fromLocal8Bit(toDelete[i].path.c_str());
+ QFile file(path);
+ QFileInfo fileInfo(file);
+ if (fileInfo.exists())
+ {
+ file.remove();
+ }
+ else
+ {
+ Logger::Info("File \"%s\" has already been deleted\n", toDelete[i].path.c_str());
+ }
+ }
+
+ /* download files */
+ vector<pair<string, string> > files;
+ vector<Config::FileEntry> downloadList = cfg->GetDownloadList();
+ for (unsigned i = 0; i < downloadList.size(); i++)
+ {
+ QString path = QString::fromLocal8Bit(downloadList[i].path.c_str());
+ QFileInfo fileInfo(path);
+ if (fileInfo.exists())
+ {
+ Logger::Info("File \"%s\" already exists\n", downloadList[i].path.c_str());
+ /**
+ * @todo Compute md5 hash and check if they are the same
+ */
+ }
+ else
+ {
+ pair<string, string> file = make_pair(downloadList[i].path, downloadList[i].md5);
+ files.push_back(file);
+ }
+ }
+
+ if (files.size() != 0)
+ {
+ Logger::Debug("Setting server address to %s\n", cfg->GetServerAddr().c_str());
+
+ QString addr = QString::fromLocal8Bit(cfg->GetServerAddr().c_str());
+ DownloadClient downloadClient(addr);
+ downloadClient.Download(files);
+ }
+ else
+ {
+ Logger::Trace("No files to download from server.\n");
+ }
+} \ No newline at end of file
diff --git a/client/FileOpThread.h b/client/FileOpThread.h
new file mode 100644
index 0000000..29731c9
--- /dev/null
+++ b/client/FileOpThread.h
@@ -0,0 +1,25 @@
+
+
+#ifndef FILE_OP_THREAD_H
+#define FILE_OP_THREAD_H
+
+#include <QThread>
+
+/**
+ * @brief Special thread to process all file operations
+ */
+class FileOpThread: public QThread
+{
+public:
+ /**
+ * @brief Initialize new FIleOpThread instance
+ */
+ FileOpThread() {}
+
+ /**
+ * @brief Thread main loop
+ */
+ void run();
+};
+
+#endif \ No newline at end of file
diff --git a/client/ProxyClientApp.cpp b/client/ProxyClientApp.cpp
index 4b233e5..94d8a7c 100644
--- a/client/ProxyClientApp.cpp
+++ b/client/ProxyClientApp.cpp
@@ -5,6 +5,7 @@
#include "client.h"
#include "Dialog.h"
+#include "FileOpThread.h"
#include "ProxyClientApp.h"
#include "UpdatedConfig.h"
@@ -84,6 +85,9 @@ void ProxyClientApp::showProxyDialog()
void ProxyClientApp::configUpdated()
{
+ FileOpThread fileOpThread;
+ fileOpThread.start(QThread::NormalPriority);
+
UpdatedConfig *cfg = UpdatedConfig::CurrentConfig();
QString msg = QString::fromLocal8Bit(cfg->ConfigLoadedMsg.c_str());
QMessageBox updatedMsg;
@@ -92,10 +96,6 @@ void ProxyClientApp::configUpdated()
updatedMsg.setStandardButtons(QMessageBox::Ok);
updatedMsg.setIcon(QMessageBox::Information);
updatedMsg.exec();
-
- /* delete files */
-
- /* download files */
}
void ProxyClientApp::quitApp()
diff --git a/client/ProxyClientApp.h b/client/ProxyClientApp.h
index 83c7c31..5dd0a69 100644
--- a/client/ProxyClientApp.h
+++ b/client/ProxyClientApp.h
@@ -10,13 +10,16 @@
class ProxyClientApp: public QApplication
{
Q_OBJECT
+
public:
ProxyClientApp(int &argc, char *argv[]);
+
private slots:
void trayActivated(QSystemTrayIcon::ActivationReason reason);
void showProxyDialog();
void configUpdated();
void quitApp();
+
private:
QSystemTrayIcon *trayIcon;
};
diff --git a/client/SslClient.cpp b/client/SslClient.cpp
index b3a2d15..b1841ed 100644
--- a/client/SslClient.cpp
+++ b/client/SslClient.cpp
@@ -1,4 +1,5 @@
+#include <string.h>
#include <QtCore>
#include <QtNetwork>
#include "SslClient.h"
@@ -72,7 +73,8 @@ void SslClient::SendRequest(RequestType type)
if (sslSocket.state() != QAbstractSocket::ConnectedState)
{
Logger::Trace("Connecting to server %s:%u\n", server.toLocal8Bit().data(), port);
- sslSocket.connectToHostEncrypted(server, port);
+ //sslSocket.connectToHostEncrypted(server, port);
+ sslSocket.connectToHostEncrypted("127.0.0.1", port);
}
else
{
@@ -100,6 +102,33 @@ void SslClient::SendRequest(RequestType type)
sslSocket.write(pkt);
}
+void SslClient::SendFileRequest(string filename)
+{
+ Logger::Trace("Sending request w code %x\n", RegularFile);
+ if (sslSocket.state() != QAbstractSocket::ConnectedState)
+ {
+ Logger::Trace("Connecting to server %s:%u\n", server.toLocal8Bit().data(), port);
+ sslSocket.connectToHostEncrypted(server, port);
+ }
+ else
+ {
+ Logger::Trace("Already connected to %s:%u\n", server.toLocal8Bit().data(), port);
+ }
+
+ unsigned char rcode = 0x12;
+ const char *file = filename.c_str();
+ size_t path_len = strlen(file);
+ char data[path_len + 5];
+ data[0] = data[1] = 0x13;
+ data[2] = rcode;
+ strncpy(data + 3, file, path_len);
+ data[path_len - 1] = data[path_len - 2] = 0x14;
+
+ QByteArray pkt(data);
+ sslSocket.write(pkt);
+}
+
+
/*
* Signal handlers
*/
diff --git a/client/SslClient.h b/client/SslClient.h
index 8172bad..a6b981c 100644
--- a/client/SslClient.h
+++ b/client/SslClient.h
@@ -88,13 +88,13 @@ public:
};
/**
- * @brief setup ssl socket ans it's type, certificates and key<br/>
+ * @brief Setup ssl socket ans it's type, certificates and key<br/>
* Default server address will be used: 127.0.0.1
*/
SslClient();
/**
- * @brief setup ssl socket ans it's type, certificates and key
+ * @brief Setup ssl socket and it's type, certificates and key
* @param addr server address or hostname to connect to
*/
SslClient(QString addr);
@@ -106,15 +106,22 @@ public:
void SetServerAddr(QString addr);
/**
- * @brief Request generic proxy list
+ * @brief Send request to server
* @param type type of request to send
*/
void SendRequest(RequestType type);
/**
+ * @brief Send file data request (RequestType::RegularFile)
+ * @param File name on client machine (will be sent to server)
+ */
+ void SendFileRequest(string filename);
+
+ /**
* @brief disconnect from server
*/
void Disconnect();
+
signals:
/**
* @brief This signal is emited when data is recieved as a reply to
@@ -128,6 +135,7 @@ signals:
* @todo emit this signal on all SSL errors too
*/
void ConnectionError();
+
private slots:
void Connected();
void Disconnected();
@@ -135,9 +143,12 @@ private slots:
void Error(QAbstractSocket::SocketError socketError);
void PeerVerifyError(const QSslError &error);
void SslErrors(const QList<QSslError> &errors);
+
+protected:
+ QString server;
+
private:
QSslSocket sslSocket;
- QString server;
unsigned short port;
};
diff --git a/client/UpdatedConfig.cpp b/client/UpdatedConfig.cpp
index 6c69f12..a59bc67 100644
--- a/client/UpdatedConfig.cpp
+++ b/client/UpdatedConfig.cpp
@@ -12,6 +12,16 @@ UpdatedConfig *UpdatedConfig::CurrentConfig()
return self;
}
+string UpdatedConfig::GetServerAddr()
+{
+ if (! configValid)
+ {
+ Logger::Error("No valid server records present!\n");
+ return string("");
+ }
+ return servers[activeSrvIndex].host;
+}
+
UpdatedConfig::UpdatedConfig()
{
activeSrvIndex = 0;
@@ -36,6 +46,7 @@ UpdatedConfig::UpdatedConfig()
void UpdatedConfig::update()
{
Logger::Trace("Going to update configuration\n");
+ configValid = false;
if (retryFailed)
{
@@ -147,6 +158,7 @@ end:
{
Logger::Info("Config successfully updated!\n");
client->Disconnect();
+ configValid = true;
/* reset retry params and setup timer to fire on next planned update */
time = 0;
diff --git a/client/UpdatedConfig.h b/client/UpdatedConfig.h
index 5470d4d..2e4deac 100644
--- a/client/UpdatedConfig.h
+++ b/client/UpdatedConfig.h
@@ -26,6 +26,11 @@ public:
*/
static UpdatedConfig *CurrentConfig();
+ /**
+ * @brief Get valid server address to communicate with
+ * @return address of server to communicate with ot empty string
+ */
+ string GetServerAddr();
signals:
/**
* @brief Signal is emitted when client configuration is updated
diff --git a/client/client.pro b/client/client.pro
index 16de7f0..6520c5d 100644
--- a/client/client.pro
+++ b/client/client.pro
@@ -20,7 +20,9 @@ HEADERS += client.h \
Logger.h \
Config.h \
UpdatedConfig.h \
- SslClient.h
+ SslClient.h \
+ FileOpThread.h \
+ DownloadClient.h
SOURCES += Dialog.cpp \
main.cpp \
@@ -29,7 +31,9 @@ SOURCES += Dialog.cpp \
Logger.cpp \
Config.cpp \
UpdatedConfig.cpp \
- SslClient.cpp
+ SslClient.cpp \
+ FileOpThread.cpp \
+ DownloadClient.cpp
OTHER_FILES +=