#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 ? dot - start : -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), _curTransaction(0), _curTransfer(0), _curPath() { 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.toJson().object()); break; case 0x4002: // Reply to file delete handleDeleteResult(msg.toJson().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() != _curTransaction) { 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; } else { qDebug() << "Transfer finished succesfully"; } cleanCurTransaction(); handleQueue(); } void FmsManager::handleDeleteResult(const QJsonObject &msg) { if (msg["transaction_id"].toInt() != _curTransaction) { qWarning() << "Received a result for an invalid transaction id"; return; } int result = msg["result"].toInt(); if (result != 0) { qWarning() << "FMS delete file failed with result" << result; } else { qDebug() << "Deleted file succesfully"; } cleanCurTransaction(); handleQueue(); } void FmsManager::handleQueue() { if (_pending.isEmpty()) { qDebug() << "Queue empty"; return; } if (_curTransaction) { qDebug() << "Already in transaction"; return; } if (!_obex->isConnected()) { qDebug() << "Currently not connected"; 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)); qDebug() << "Uploading file" << path; _toq->sendMessage(ToqConnection::FMSEndpoint, ToqConnection::FMSEndpoint + 1, transactionId, 1, obj); _curTransaction = transactionId; _curTransfer = _obex->put(name, file.contents); _curPath = path; connect(_curTransfer, &ObexTransfer::error, this, &FmsManager::handleObexError); } else { int transactionId = _toq->newTransactionId(); QJsonObject obj; obj.insert("file_path", path); obj.insert("transaction_id", transactionId); obj.insert("type", QLatin1String("file")); qDebug() << "Deleting remote file" << path; _toq->sendMessage(ToqConnection::FMSEndpoint, ToqConnection::FMSEndpoint + 1, transactionId, 2, obj); _curTransaction = transactionId; _curPath = path; } } void FmsManager::handleToqDisconnected() { _pending.clear(); if (_curTransfer) { _curTransfer->cancel(); } cleanCurTransaction(); } 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" << _curPath; cleanCurTransaction(); } void FmsManager::cleanCurTransaction() { if (_curTransaction) { qDebug() << "Clearing current transaction"; _curTransaction = 0; } if (_curTransfer) { _curTransfer->deleteLater(); _curTransfer = 0; } _curPath.clear(); }