summaryrefslogtreecommitdiff
path: root/distfoldd/clientagent.cc
diff options
context:
space:
mode:
authorJavier S. Pedro <maemo@javispedro.com>2012-09-17 23:03:03 +0200
committerJavier S. Pedro <maemo@javispedro.com>2012-09-17 23:03:03 +0200
commitc3a1946675855b299a2b36550cdf2c2f69d153aa (patch)
treef7adf66404cdc47994225b616bcaf082a07dd168 /distfoldd/clientagent.cc
downloaddistfold-c3a1946675855b299a2b36550cdf2c2f69d153aa.tar.gz
distfold-c3a1946675855b299a2b36550cdf2c2f69d153aa.zip
initial import
Diffstat (limited to 'distfoldd/clientagent.cc')
-rw-r--r--distfoldd/clientagent.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/distfoldd/clientagent.cc b/distfoldd/clientagent.cc
new file mode 100644
index 0000000..f77a21a
--- /dev/null
+++ b/distfoldd/clientagent.cc
@@ -0,0 +1,174 @@
+#include <QtCore/QDebug>
+
+#include "clientagent.h"
+
+ClientAgent::ClientAgent(const QHostAddress& addr, uint port, const QDir& local_dir, SyncFlags flags, QObject *parent) :
+ Agent(new QSslSocket, local_dir, flags, parent)
+{
+ qDebug() << "Starting client agent at" << QDateTime::currentDateTime();
+ _socket->setParent(this); // Can't set parent until QObject constructed
+ _socket->connectToHostEncrypted(addr.toString(), port);
+ sendMessage(MSG_HELLO);
+ _state = STATE_HELLO;
+}
+
+void ClientAgent::handleMessage(MessageType msg, const QByteArray &data)
+{
+ qDebug() << "Client::handleMessage" << msg << data.size();
+ switch (msg) {
+ case MSG_HELLO_REPLY:
+ Q_ASSERT(_state == STATE_HELLO);
+ qDebug() << "Hello reply";
+ _state = STATE_FILE_LIST;
+ sendFileList();
+ break;
+ case MSG_FILE_ACTIONS_REPLY:
+ Q_ASSERT(_state == STATE_FILE_LIST);
+ handleActionInfoList(decodeActionInfoList(data));
+ break;
+ case MSG_PULL_FILE_REPLY:
+ Q_ASSERT(_state == STATE_FILE_ACTIONS && !_pendingActions.empty());
+ handlePulledFile(data);
+ break;
+ default:
+ qWarning() << "Unknown message";
+ break;
+ }
+}
+
+void ClientAgent::sendFileList()
+{
+ QFileInfoList list = scanFiles(QDir(wireToLocalPath(_subPath)));
+ sendMessage(MSG_FILE_LIST, encodeFileInfoList(list));
+}
+
+void ClientAgent::handleActionInfoList(const RemoteActionInfoList &list)
+{
+ foreach (const RemoteActionInfo& info, list) {
+ switch (info.action()) {
+ case ACTION_NONE:
+ qDebug() << " = " << info.fileInfo().name();
+ break;
+ case ACTION_PULL:
+ qDebug() << " < " << info.fileInfo().name();
+ break;
+ case ACTION_PULL_METADATA:
+ qDebug() << " <m" << info.fileInfo().name();
+ break;
+ case ACTION_PULL_DELETE:
+ qDebug() << " <d" << info.fileInfo().name();
+ break;
+ case ACTION_PUSH:
+ qDebug() << " > " << info.fileInfo().name();
+ break;
+ case ACTION_PUSH_METADATA:
+ qDebug() << " >m" << info.fileInfo().name();
+ break;
+ case ACTION_PUSH_DELETE:
+ qDebug() << " >d" << info.fileInfo().name();
+ break;
+ }
+ }
+
+ _pendingActions = list;
+ _state = STATE_FILE_ACTIONS;
+ executeNextAction();
+}
+
+void ClientAgent::executeNextAction()
+{
+ if (_pendingActions.empty()) {
+ qDebug() << "Done";
+ emit finished();
+ sendMessage(MSG_BYE);
+ _socket->flush();
+ _socket->close();
+ return;
+ }
+
+ qDebug() << "Remaining actions" << _pendingActions.count();
+
+ const RemoteActionInfo& info = _pendingActions.first();
+ const QString wire_path = info.fileInfo().name();
+ const QString local_path = wireToLocalPath(wire_path);
+ switch (info.action()) {
+ case ACTION_PULL:
+ if (_flags & SYNC_READ_ONLY) break;
+ if (info.fileInfo().isDir()) {
+ if (!QDir().mkpath(local_path)) {
+ qWarning() << "Failed to create local path" << local_path;
+ }
+ } else {
+ sendMessage(MSG_PULL_FILE, encodeFileName(wire_path));
+ return; // Wait for the pulled file message.
+ }
+ break;
+ case ACTION_PULL_METADATA:
+ if (_flags & SYNC_READ_ONLY) break;
+ setLocalFileDateTime(local_path, info.fileInfo().lastModified());
+ break;
+ case ACTION_PULL_DELETE:
+ handleDeleteFile(wire_path);
+ break;
+ case ACTION_PUSH:
+ handlePushFile(wire_path);
+ break;
+ case ACTION_PUSH_METADATA:
+ sendMessage(MSG_PUSH_FILE_METADATA,
+ encodeFileInfoList(QFileInfoList() << QFileInfo(local_path)));
+ break;
+ case ACTION_PUSH_DELETE:
+ sendMessage(MSG_DELETE_FILE, encodeFileName(wire_path));
+ break;
+ default:
+ qWarning() << "Unknown action" << info.action();
+ break;
+ }
+ _pendingActions.removeFirst();
+ executeNextAction();
+}
+
+void ClientAgent::handlePulledFile(const QByteArray &data)
+{
+ const RemoteActionInfo& info = _pendingActions.takeFirst();
+ if (_flags & SYNC_READ_ONLY) return;
+ QString local_path(wireToLocalPath(info.fileInfo().name()));
+ QFile file(local_path);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ file.write(Compressor::decompress(data));
+ file.close();
+ setLocalFileDateTime(local_path, info.fileInfo().lastModified());
+ } else {
+ qWarning() << "Failed to open" << file.fileName() << "for writing";
+ }
+ executeNextAction();
+}
+
+void ClientAgent::handlePushFile(const QString &path)
+{
+ QFile file(wireToLocalPath(path));
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray file_data = file.readAll();
+ if (_flags & SYNC_COMPRESS) file_data = Compressor::compress(file_data);
+ QByteArray ba = encodeFileNameItem(path) + file_data;
+ sendMessage(MSG_PUSH_FILE, ba);
+ } else {
+ qWarning() << "Failed to open file" << file.fileName() << "for reading";
+ }
+}
+
+void ClientAgent::handleDeleteFile(const QString &wire_path)
+{
+ if (_flags & SYNC_READ_ONLY) return;
+ QFileInfo local(wireToLocalPath(wire_path));
+ QString local_path = local.absoluteFilePath();
+ if (local.isDir()) {
+ if (!QDir().rmdir(local_path)) {
+ qWarning() << "Failed to remove local dir" << local_path;
+ }
+ } else {
+ if (!QDir().remove(local_path)) {
+ qWarning() << "Failed to remove local file" << local_path;
+ }
+ }
+}