Commit 44a3d071 authored by Anthony Léonard's avatar Anthony Léonard Committed by Guillaume Roguez

fix code for datatransfer

Many fixes to adapt LRC to the new datatransfer.

Change-Id: Ibbe322a32d44800c54e9a7ffd99c42a57200deb7
Signed-off-by: Guillaume Roguez's avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 4ce62577
......@@ -33,6 +33,7 @@
// Data
#include "api/conversation.h"
#include "api/profile.h"
#include "api/datatransfer.h"
namespace lrc
{
......@@ -46,6 +47,8 @@ namespace api
namespace account { struct Info; }
namespace interaction { struct Info; }
class Lrc;
class BehaviorController;
class NewAccountModel;
......@@ -60,6 +63,7 @@ public:
const account::Info& owner;
ConversationModel(const account::Info& owner,
Lrc& lrc,
Database& db,
const CallbacksHandler& callbacksHandler,
const api::BehaviorController& behaviorController);
......@@ -154,6 +158,8 @@ public:
void cancelTransfer(const std::string& convUid, uint64_t interactionId);
void getTransferInfo(uint64_t interactionId, api::datatransfer::Info& info);
Q_SIGNALS:
/**
* Emitted when a conversation receives a new interaction
......
......@@ -91,7 +91,7 @@ to_status(const std::string& status)
struct Info
{
const std::string uid; ///< long-term and unique identifier (used for historic)
std::string uid; ///< long-term and unique identifier (used for historic)
Status status;
bool isOutgoing;
std::size_t totalSize;
......
......@@ -52,16 +52,15 @@ class LIB_EXPORT DataTransferModel : public QObject {
Q_OBJECT
public:
DataTransferModel(Database& database,
const CallbacksHandler& callbacksHandler);
DataTransferModel();
~DataTransferModel();
void sendFile(const std::string& account_id, const std::string& peer_uri,
const std::string& file_path, const std::string& display_name);
datatransfer::Info transferInfo(const std::string& uid);
void transferInfo(long long ringId, datatransfer::Info& lrc_info);
std::streamsize bytesProgress(int interactionId);
void bytesProgress(int interactionId, int64_t& total, int64_t& progress);
void accept(int interactionId, const std::string& file_path, std::size_t offset);
......@@ -71,6 +70,8 @@ public:
int getInteractionIdFromDringId(long long dringId);
long long getDringIdFromInteractionId(int interactionId);
Q_SIGNALS:
/**
* Connect this signal to know when a data transfer is incoming.
......
......@@ -125,6 +125,7 @@ to_string(const Status& status)
return "TRANSFER_AWAITING";
case Status::TRANSFER_FINISHED:
return "TRANSFER_FINISHED";
case Status::INVALID:
default:
return "INVALID";
}
......
......@@ -34,6 +34,7 @@ namespace api
class BehaviorController;
class NewAccountModel;
class DataTransferModel;
class LIB_EXPORT Lrc {
public:
......@@ -49,6 +50,11 @@ public:
* @return a BehaviorController&.
*/
const BehaviorController& getBehaviorController() const;
/**
* get a reference on the DataTransfer controller.
* @return a DataTransferModel&.
*/
DataTransferModel& getDataTransferModel() const;
private:
std::unique_ptr<LrcPimpl> lrcPimpl_;
......
......@@ -39,6 +39,8 @@ class NewAccountModelPimpl;
namespace api
{
class Lrc;
class BehaviorController;
namespace account { struct Info; }
......@@ -51,7 +53,8 @@ class LIB_EXPORT NewAccountModel : public QObject {
public:
using AccountInfoMap = std::map<std::string, account::Info>;
NewAccountModel(Database& database,
NewAccountModel(Lrc& lrc,
Database& database,
const CallbacksHandler& callbackHandler,
const api::BehaviorController& behaviorController);
......
......@@ -20,6 +20,8 @@
#include "api/profile.h"
#include "api/datatransfer.h"
#include <datatransfer_interface.h>
namespace lrc
{
......@@ -181,7 +183,7 @@ getHistory(Database& db, api::conversation::Info& conversation)
{{":conversation_id", conversation.uid}});
if (interactionsResult.nbrOfCols == 6) {
auto payloads = interactionsResult.payloads;
for (auto i = 0; i < payloads.size(); i += 6) {
for (decltype(payloads.size()) i = 0; i < payloads.size(); i += 6) {
auto msg = api::interaction::Info({payloads[i + 1], payloads[i + 2],
std::stoi(payloads[i + 3]),
api::interaction::to_type(payloads[i + 4]),
......@@ -214,21 +216,30 @@ int
addDataTransferToConversation(Database& db,
const std::string& accountProfileId,
const std::string& conversationId,
const DataTransferInfo& infoFromDaemon)
const api::datatransfer::Info& infoFromDaemon)
{
auto peerProfileId = getProfileId(db, infoFromDaemon.peer.toStdString());
auto authorId = (infoFromDaemon.isOutgoing) ? peerProfileId : peerProfileId;
return db.insertInto("interactions",
{{":account_id", "account_id"}, {":author_id", "author_id"},
{":conversation_id", "conversation_id"}, {":timestamp", "timestamp"},
{":body", "body"}, {":type", "type"},
{":status", "status"}},
{{":account_id", accountProfileId}, {":author_id", authorId},
auto peerProfileId = getProfileId(db, infoFromDaemon.peerUri);
auto authorId = peerProfileId;
return db.insertInto("interactions", {
{":account_id", "account_id"},
{":author_id", "author_id"},
{":conversation_id", "conversation_id"},
{":timestamp", "timestamp"},
{":body", "body"},
{":type", "type"},
{":status", "status"}
}, {
{":account_id", accountProfileId},
{":author_id", authorId},
{":conversation_id", conversationId},
{":timestamp", std::to_string(std::time(nullptr))},
{":body", infoFromDaemon.displayName.toStdString()}, {":type", (infoFromDaemon.isOutgoing)?"OUTGOING_DATA_TRANSFER":"INCOMING_DATA_TRANSFER"},
{":status", "TRANSFER_CREATED"}});
{":body", infoFromDaemon.displayName},
{":type", infoFromDaemon.isOutgoing ?
"OUTGOING_DATA_TRANSFER" :
"INCOMING_DATA_TRANSFER"},
{":status", "TRANSFER_CREATED"}
});
}
int
......@@ -296,6 +307,21 @@ void updateInteractionStatus(Database& db, unsigned int id,
"id=:id", {{":id", std::to_string(id)}});
}
std::string
conversationIdFromInteractionId(Database& db, unsigned int interactionId)
{
auto result = db.select("conversation_id",
"interactions",
"id=:interaction_id",
{{":interaction_id", std::to_string(interactionId)}});
if (result.nbrOfCols == 1) {
auto payloads = result.payloads;
return payloads[0];
}
return {};
}
void clearHistory(Database& db,
const std::string& conversationId)
{
......
......@@ -29,6 +29,10 @@
namespace lrc
{
namespace api { namespace datatransfer {
struct Info;
}}
namespace authority
{
......@@ -232,7 +236,10 @@ int countUnreadFromInteractions(Database& db, const std::string& conversationId)
int addDataTransferToConversation(Database& db,
const std::string& accountProfileId,
const std::string& conversationId,
const DataTransferInfo& infoFromDaemon);
const api::datatransfer::Info& infoFromDaemon);
std::string conversationIdFromInteractionId(Database& db, unsigned int interactionId);
} // namespace database
} // namespace authority
......
......@@ -22,7 +22,7 @@
#include "api/account.h"
#include "api/lrc.h"
#include "api/newaccountmodel.h"
#include "api/datatransfer.h"
#include "api/datatransfermodel.h"
// Lrc
#include "account.h"
......@@ -218,8 +218,9 @@ CallbacksHandler::slotRegistrationStateChanged(const QString& accountId,
unsigned detail_code,
const QString& detail_str)
{
(void) detail_code;
(void) detail_str;
emit accountStatusChanged(accountId.toStdString(), lrc::api::account::to_status(registration_state.toStdString()));
}
void
......@@ -286,28 +287,35 @@ CallbacksHandler::slotDataTransferEvent(qulonglong dringId, uint codeStatus)
{
auto event = DRing::DataTransferEventCode(codeStatus);
api::datatransfer::Info info;
parent.getDataTransferModel().transferInfo(dringId, info);
// WARNING: info.status could be INVALID in case of async signaling
// So listeners must only take account of dringId in such case.
// Is useful for "termination" status like unjoinable_peer.
switch (event) {
case DRing::DataTransferEventCode::created:
emit incomingTransfer(static_cast<long long>(dringId));
emit transferStatusCreated(static_cast<long long>(dringId), info);
break;
case DRing::DataTransferEventCode::closed_by_host:
case DRing::DataTransferEventCode::closed_by_peer:
emit transferStatusCanceled(static_cast<long long>(dringId));
emit transferStatusCanceled(static_cast<long long>(dringId), info);
break;
case DRing::DataTransferEventCode::wait_peer_acceptance:
case DRing::DataTransferEventCode::wait_host_acceptance:
emit transferStatusAwaiting(static_cast<long long>(dringId));
emit transferStatusAwaiting(static_cast<long long>(dringId), info);
break;
case DRing::DataTransferEventCode::ongoing:
emit transferStatusOngoing(static_cast<long long>(dringId));
emit transferStatusOngoing(static_cast<long long>(dringId), info);
break;
case DRing::DataTransferEventCode::finished:
emit transferStatusFinished(static_cast<long long>(dringId));
emit transferStatusFinished(static_cast<long long>(dringId), info);
break;
case DRing::DataTransferEventCode::invalid_pathname:
case DRing::DataTransferEventCode::unjoinable_peer:
case DRing::DataTransferEventCode::unsupported:
emit transferStatusError(static_cast<long long>(dringId));
emit transferStatusError(static_cast<long long>(dringId), info);
break;
}
}
......
......@@ -27,6 +27,7 @@
// Lrc
#include "typedefs.h"
#include "namedirectory.h"
#include "api/datatransfer.h"
namespace lrc
{
......@@ -160,13 +161,12 @@ Q_SIGNALS:
const uint64_t id,
const std::string& to, int status);
void incomingTransfer(long long dringId);
//~ void transferStatusChanged(const long long dringId, uint codeStatus);
void transferStatusCanceled(long long dringId);
void transferStatusAwaiting(long long dringId);
void transferStatusOngoing(long long dringId);
void transferStatusFinished(long long dringId);
void transferStatusError(long long dringId);
void transferStatusCreated(long long dringId, api::datatransfer::Info info);
void transferStatusCanceled(long long dringId, api::datatransfer::Info info);
void transferStatusAwaiting(long long dringId, api::datatransfer::Info info);
void transferStatusOngoing(long long dringId, api::datatransfer::Info info);
void transferStatusFinished(long long dringId, api::datatransfer::Info info);
void transferStatusError(long long dringId, api::datatransfer::Info info);
private Q_SLOTS:
/**
......
......@@ -136,11 +136,6 @@ public Q_SLOTS:
void slotNewAccountMessage(std::string& accountId,
std::string& from,
std::map<std::string,std::string> payloads);
/**
* Listen from callbacksHandler for new account file transfer and add pending contact if not present
* @param dringId Id of transfer from daemon. Used to retrieve transfer informations.
*/
void slotNewAccountTransfer(long long dringId);
};
using namespace authority;
......@@ -368,9 +363,6 @@ ContactModelPimpl::ContactModelPimpl(const ContactModel& linked,
this, &ContactModelPimpl::slotIncomingCall);
connect(&callbacksHandler, &lrc::CallbacksHandler::newAccountMessage,
this, &ContactModelPimpl::slotNewAccountMessage);
connect(&callbacksHandler, &lrc::CallbacksHandler::incomingTransfer,
this, &ContactModelPimpl::slotNewAccountTransfer);
}
ContactModelPimpl::~ContactModelPimpl()
......@@ -596,30 +588,6 @@ ContactModelPimpl::slotNewAccountMessage(std::string& accountId,
emit linked.newAccountMessage(accountId, from, payloads);
}
void
ContactModelPimpl::slotNewAccountTransfer(long long dringId)
{
DataTransferInfo infoFromDaemon = ConfigurationManager::instance().dataTransferInfo(dringId);
auto accountId = infoFromDaemon.accountId.toStdString();
auto peerId = infoFromDaemon.peer.toStdString(); // TODO valeur à checker
if (accountId != linked.owner.id) return;
auto* account = AccountModel::instance().getById(linked.owner.id.c_str());
if (not account) {
qDebug() << "ContactModel::slotNewAccountTransfer(), nullptr";
return;
}
if (contacts.find(peerId) == contacts.end()) {
// Contact not found, load profile from database.
// The conversation model will create an entry and link the incomingCall.
auto* cm = PhoneDirectoryModel::instance().getNumber(infoFromDaemon.peer, account);
addToContacts(cm, profile::Type::PENDING);
}
emit linked.newAccountTransfer(dringId, infoFromDaemon);
}
} // namespace lrc
#include "api/moc_contactmodel.cpp"
......
This diff is collapsed.
......@@ -18,8 +18,6 @@
// LRC
#include "api/datatransfermodel.h"
#include "callbackshandler.h"
#include "database.h"
// Dbus
#include "dbus/configurationmanager.h"
......@@ -30,18 +28,20 @@
// Std
#include <map>
#include <stdexcept>
#include <type_traits>
// Qt
#include <QUuid>
namespace lrc { namespace api {
/// DRING to LRC event code conversion
// DRING to LRC event code conversion
static inline
datatransfer::Status
convertDataTransferEvent(DRing::DataTransferEventCode event)
{
switch (event) {
case DRing::DataTransferEventCode::invalid: return datatransfer::Status::INVALID;
case DRing::DataTransferEventCode::created: return datatransfer::Status::on_connection;
case DRing::DataTransferEventCode::unsupported: return datatransfer::Status::unsupported;
case DRing::DataTransferEventCode::wait_peer_acceptance: return datatransfer::Status::on_connection;
......@@ -61,25 +61,17 @@ class DataTransferModel::Impl : public QObject
Q_OBJECT
public:
Impl(DataTransferModel& up_link,
Database& database,
const CallbacksHandler& callbacksHandler);
Impl(DataTransferModel& up_link);
std::vector<std::string> transferIdList() const;
DataTransferModel& upLink;
std::map<long long, int> dring2lrcIdMap;
std::map<int, long long> lrc2dringIdMap; // stricly the reverse map of dring2lrcIdMap
Database& database;
const CallbacksHandler& callbacksHandler;
};
DataTransferModel::Impl::Impl(DataTransferModel& up_link,
Database& database,
const CallbacksHandler& callbacksHandler)
DataTransferModel::Impl::Impl(DataTransferModel& up_link)
: QObject {}
, callbacksHandler {callbacksHandler}
, database {database}
, upLink {up_link}
{}
......@@ -93,10 +85,9 @@ DataTransferModel::registerTransferId(long long dringId, int interactionId)
}
DataTransferModel::DataTransferModel(Database& database,
const CallbacksHandler& callbacksHandler)
DataTransferModel::DataTransferModel()
: QObject()
, pimpl_ { std::make_unique<Impl>(*this, database, callbacksHandler) }
, pimpl_ { std::make_unique<Impl>(*this) }
{}
DataTransferModel::~DataTransferModel() = default;
......@@ -116,21 +107,58 @@ DataTransferModel::Impl::transferIdList() const
return result;
}
void
DataTransferModel::transferInfo(long long ringId, datatransfer::Info& lrc_info)
{
DataTransferInfo infoFromDaemon;
if (ConfigurationManager::instance().dataTransferInfo(ringId, infoFromDaemon) == 0) {
#if 0
int interactionId;
try {
interactionId = pimpl_->dring2lrcIdMap.at(ringId);
} catch (...) {
interactionId = -1;
}
#endif
//lrc_info.uid = ?
lrc_info.status = convertDataTransferEvent(DRing::DataTransferEventCode(infoFromDaemon.lastEvent));
lrc_info.isOutgoing = !(infoFromDaemon.flags & (1 << uint32_t(DRing::DataTransferFlags::direction)));
lrc_info.totalSize = infoFromDaemon.totalSize;
lrc_info.progress = infoFromDaemon.bytesProgress;
lrc_info.path = infoFromDaemon.displayName.toStdString();
lrc_info.displayName = infoFromDaemon.displayName.toStdString();
lrc_info.accountId = infoFromDaemon.accountId.toStdString();
lrc_info.peerUri = infoFromDaemon.peer.toStdString();
//lrc_info.timestamp = ?
return;
}
lrc_info.status = datatransfer::Status::INVALID;
}
void
DataTransferModel::sendFile(const std::string& account_id, const std::string& peer_uri,
const std::string& file_path, const std::string& display_name)
{
auto dring_id = static_cast<DRing::DataTransferId>(ConfigurationManager::instance().sendFile(
QString::fromStdString(account_id),
QString::fromStdString(peer_uri),
QString::fromStdString(file_path),
QString::fromStdString(display_name)));
DataTransferInfo info;
qulonglong id;
info.accountId = QString::fromStdString(account_id);
info.peer = QString::fromStdString(peer_uri);
info.path = QString::fromStdString(file_path);
info.displayName = QString::fromStdString(display_name);
info.bytesProgress = 0;
if (ConfigurationManager::instance().sendFile(info, id) != 0) {
qDebug() << "DataTransferModel::sendFile(), error";
return;
}
}
std::streamsize
DataTransferModel::bytesProgress(int interactionId)
void
DataTransferModel::bytesProgress(int interactionId, int64_t& total, int64_t& progress)
{
return ConfigurationManager::instance().dataTransferBytesProgress(pimpl_->lrc2dringIdMap.at(interactionId));
ConfigurationManager::instance().dataTransferBytesProgress(pimpl_->lrc2dringIdMap.at(interactionId),
reinterpret_cast<qlonglong&>(total),
reinterpret_cast<qlonglong&>(progress));
}
void
......@@ -155,6 +183,12 @@ DataTransferModel::getInteractionIdFromDringId(long long dringId)
return pimpl_->dring2lrcIdMap.at(dringId);
}
long long
DataTransferModel::getDringIdFromInteractionId(int interactionId)
{
return pimpl_->lrc2dringIdMap.at(interactionId);
}
}} // namespace lrc::api
#include "api/moc_datatransfermodel.cpp"
......
......@@ -43,38 +43,19 @@ Q_DECLARE_METATYPE(MapStringVectorString)
Q_DECLARE_METATYPE(VectorVectorByte)
Q_DECLARE_METATYPE(DataTransferInfo)
#ifndef ENABLE_LIBWRAP
static bool dbus_metaTypeInit = false;
#endif
inline void registerCommTypes() {
#ifndef ENABLE_LIBWRAP
qDBusRegisterMetaType<MapStringString> ();
qDBusRegisterMetaType<MapStringInt> ();
qDBusRegisterMetaType<VectorMapStringString> ();
qDBusRegisterMetaType<MapStringMapStringVectorString>();
qDBusRegisterMetaType<VectorInt> ();
qDBusRegisterMetaType<VectorUInt> ();
qDBusRegisterMetaType<VectorULongLong> ();
qDBusRegisterMetaType<VectorString> ();
qDBusRegisterMetaType<MapStringVectorString> ();
qDBusRegisterMetaType<VectorVectorByte> ();
qDBusRegisterMetaType<DataTransferInfo> ();
dbus_metaTypeInit = true;
#endif
}
#ifndef ENABLE_LIBWRAP
static inline QDBusArgument &operator<<(QDBusArgument& argument, const DataTransferInfo& info)
{
argument.beginStructure();
argument << info.isOutgoing;
argument << info.accountId;
argument << info.lastEvent;
argument << info.flags;
argument << info.totalSize;
argument << info.bytesProgress;
argument << info.peer;
argument << info.displayName;
argument << info.path;
argument << info.accountId;
argument << info.peer;
argument << info.mimetype;
argument.endStructure();
return argument;
......@@ -83,19 +64,40 @@ static inline QDBusArgument &operator<<(QDBusArgument& argument, const DataTrans
static inline const QDBusArgument &operator>>(const QDBusArgument& argument, DataTransferInfo& info)
{
argument.beginStructure();
argument >> info.isOutgoing;
argument >> info.accountId;
argument >> info.lastEvent;
argument >> info.flags;
argument >> info.totalSize;
argument >> info.bytesProgress;
argument >> info.peer;
argument >> info.displayName;
argument >> info.path;
argument >> info.accountId;
argument >> info.peer;
argument >> info.mimetype;
argument.endStructure();
return argument;
}
#endif
#ifndef ENABLE_LIBWRAP
static bool dbus_metaTypeInit = false;
#endif
inline void registerCommTypes() {
#ifndef ENABLE_LIBWRAP
qDBusRegisterMetaType<MapStringString> ();
qDBusRegisterMetaType<MapStringInt> ();
qDBusRegisterMetaType<VectorMapStringString> ();
qDBusRegisterMetaType<MapStringMapStringVectorString>();
qDBusRegisterMetaType<VectorInt> ();
qDBusRegisterMetaType<VectorUInt> ();
qDBusRegisterMetaType<VectorULongLong> ();
qDBusRegisterMetaType<VectorString> ();
qDBusRegisterMetaType<MapStringVectorString> ();
qDBusRegisterMetaType<VectorVectorByte> ();
qDBusRegisterMetaType<DataTransferInfo> ();
dbus_metaTypeInit = true;
#endif
}
#pragma GCC diagnostic pop
......@@ -20,6 +20,7 @@
// Models and database
#include "api/newaccountmodel.h"
#include "api/datatransfermodel.h"
#include "api/behaviorcontroller.h"