#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), _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(); } }