summaryrefslogtreecommitdiff
path: root/saltoqd/fmsmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'saltoqd/fmsmanager.cpp')
-rw-r--r--saltoqd/fmsmanager.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/saltoqd/fmsmanager.cpp b/saltoqd/fmsmanager.cpp
new file mode 100644
index 0000000..26e147b
--- /dev/null
+++ b/saltoqd/fmsmanager.cpp
@@ -0,0 +1,157 @@
+#include "obexconnection.h"
+#include "fmsmanager.h"
+
+static QString generate_send_name(const QString &path, int transactionId, int checksum)
+{
+ Q_UNUSED(checksum);
+ int slash = path.lastIndexOf('/');
+ int dot = path.lastIndexOf('.');
+
+ int start = slash >= 0 ? slash + 1 : 0;
+ int len = dot > start ? (path.length() - 1) - (dot + 1) : -1;
+
+ QString base = path.mid(start, len);
+ QString ext;
+
+ if (len != -1) {
+ ext = path.mid(dot + 1);
+ }
+
+ return QString("%1_%2.%3").arg(base).arg(transactionId).arg(ext);
+}
+
+FmsManager::FmsManager(ObexConnection *obex, ToqManager *toq) :
+ QObject(toq), _obex(obex), _toq(toq),
+ _curTransfer(0)
+{
+ connect(_toq, &ToqManager::disconnected,
+ this, &FmsManager::handleToqDisconnected);
+ connect(_obex, &ObexConnection::connected,
+ this, &FmsManager::handleObexConnected);
+ connect(_obex, &ObexConnection::disconnected,
+ this, &FmsManager::handleObexDisconnected);
+
+ _toq->setEndpointListener(ToqConnection::FMSEndpoint, this);
+}
+
+void FmsManager::handleMessage(const ToqConnection::Message &msg)
+{
+ Q_ASSERT(msg.destination == ToqConnection::FMSEndpoint);
+ switch (msg.type) {
+ case 0x4001: // Reply to file transfer
+ handleTransferResult(msg.payload.object());
+ break;
+ default:
+ qWarning() << "Unknown message type" << msg.type;
+ break;
+ }
+}
+
+void FmsManager::updateFile(const QString &path, const QByteArray &contents)
+{
+ File& file = _files[path];
+ quint32 checksum = ToqConnection::checksum(contents);
+ file.mtime = QDateTime::currentDateTimeUtc();
+ if (checksum != file.checksum) {
+ file.contents = contents;
+ file.checksum = checksum;
+ _pending.insert(path);
+ handleQueue();
+ }
+}
+
+void FmsManager::deleteFile(const QString &path)
+{
+ if (_files.contains(path)) {
+ _files.remove(path);
+ _pending.insert(path);
+ handleQueue();
+ }
+}
+
+void FmsManager::handleTransferResult(const QJsonObject &msg)
+{
+ if (msg["transaction_id"].toInt() != _curTransferTransactionId) {
+ qWarning() << "Received a result for an invalid transaction id";
+ return;
+ }
+
+ int result = msg["result"].toInt();
+ if (result != 0) {
+ qWarning() << "FMS transfer file failed with result" << result;
+ }
+
+ cleanCurTransfer();
+ handleQueue();
+}
+
+void FmsManager::handleQueue()
+{
+ if (_pending.isEmpty()) return;
+ if (_curTransfer) return;
+ if (!_obex->isConnected()) return;
+
+ QString path = *_pending.begin();
+ _pending.remove(path);
+
+ if (_files.contains(path)) {
+ File &file = _files[path];
+ int transactionId = _toq->newTransactionId();
+ QString name = generate_send_name(path, transactionId, file.checksum);
+
+ QJsonObject obj;
+ obj.insert("sent_file_name", name);
+ obj.insert("file_path", path);
+ obj.insert("transaction_id", transactionId);
+ obj.insert("checksum", qint64(file.checksum));
+
+ _toq->sendMessage(ToqConnection::FMSEndpoint, ToqConnection::FMSEndpoint + 1,
+ transactionId, 1, obj);
+
+ _curTransfer = _obex->put(name, file.contents);
+ _curTransferTransactionId = transactionId;
+ _curTransferPath = path;
+
+ connect(_curTransfer, &ObexTransfer::error,
+ this, &FmsManager::handleObexError);
+ } else {
+ // TODO Remove files!
+ }
+}
+
+void FmsManager::handleToqDisconnected()
+{
+ _pending.clear();
+ if (_curTransfer) {
+ _curTransfer->cancel();
+ cleanCurTransfer();
+ }
+}
+
+void FmsManager::handleObexConnected()
+{
+ handleQueue();
+}
+
+void FmsManager::handleObexDisconnected()
+{
+ // Assume it's temporary and that we will eventually reconnect
+}
+
+void FmsManager::handleObexError(int response)
+{
+ Q_ASSERT(_curTransfer == sender());
+ Q_UNUSED(response);
+ qWarning() << "OBEX error while uploading" << _curTransferPath;
+ cleanCurTransfer();
+}
+
+void FmsManager::cleanCurTransfer()
+{
+ if (_curTransfer) {
+ _curTransfer->deleteLater();
+ _curTransfer = 0;
+ _curTransferTransactionId = 0;
+ _curTransferPath.clear();
+ }
+}