#include <sys/types.h>
#include <functional>
+#include <utility>
#include <vector>
#include "common/utils/logging.h"
" <method name='SendFile'>"
" <arg type='s' name='device_id' direction='in'/>"
" <arg type='s' name='file_path' direction='in'/>"
+ " <arg type='i' name='result' direction='out'/>"
" </method>"
+ " <signal name='SendFileProgressChanged'>"
+ " <arg type='s' name='file_path'/>"
+ " <arg type='x' name='send_size'/>"
+ " <arg type='x' name='total_size'/>"
+ " </signal>"
+ " <signal name='SendFileFinished'>"
+ " <arg type='i' name='result'/>"
+ " </signal>"
" </interface>"
"</node>";
const char kDBusServiceName[] = "org.tizen.capmgr";
const char kDBusObjectPath[] = "/org/tizen/capmgr";
+const char kDBusInterfaceName[] = "org.tizen.capmgr";
std::map<int, GDBusMethodInvocation*> invoc_map_;
+struct SendFileHandle {
+ const std::string file_path;
+ const std::string sender; const std::string device_id;
+ GDBusMethodInvocation* invocation;
+ GDBusConnection* connection;
+
+ SendFileHandle(std::string file_path, std::string sender,
+ std::string device_id, GDBusMethodInvocation* invocation,
+ GDBusConnection* connection)
+ : file_path(std::move(file_path)), sender(std::move(sender)),
+ device_id(std::move(device_id)), invocation(invocation),
+ connection(connection) {}
+
+ ~SendFileHandle() {
+ if (invocation)
+ g_object_unref(invocation);
+
+ if (connection) {
+ g_dbus_connection_flush_sync(connection, nullptr, nullptr);
+ g_object_unref(connection);
+ }
+ }
+};
+
+std::map<std::string, SendFileHandle*> file_map_;
+
} // namespace
namespace capmgr {
}
void DBusService::RegisterSendFileHandler(const std::string& method,
- std::function<bool(const std::string&, const std::string&)> handler) {
+ std::function<int(const std::string&, const std::string&)> handler) {
if (method == "SendFile")
EventHandler().send_file_event.connect(handler);
}
g_dbus_method_invocation_return_value(it->second, gv);
}
+void DBusService::SendFileResult(const std::string& file_path, int result) {
+ LOG(DEBUG) << "result" << result;
+ auto it = file_map_.find(file_path);
+ if (it == file_map_.end()) {
+ LOG(ERROR) << "Cannot find file handle " << file_path;
+ return;
+ } else {
+ LOG(INFO) << "Got a response for " << file_path;
+ }
+
+ SendFileHandle* handle = reinterpret_cast<SendFileHandle*>(it->second);
+ GVariant* gv = g_variant_new("(i)", result);
+ g_dbus_method_invocation_return_value(handle->invocation, gv);
+
+ delete handle;
+}
+
+void DBusService::SendFileProgress(const std::string& file_path,
+ int64_t send_size, int64_t total_size) {
+ LOG(DEBUG) << "progress" << file_path << " "
+ << send_size << "/" << total_size;
+ auto it = file_map_.find(file_path);
+ if (it == file_map_.end()) {
+ LOG(ERROR) << "Cannot find file handle " << file_path;
+ return;
+ } else {
+ LOG(INFO) << "Got a response for " << file_path;
+ }
+
+ GError* error = nullptr;
+ GVariant* gv = g_variant_new("(sxx)", file_path.c_str(), send_size,
+ total_size);
+ SendFileHandle* handle = reinterpret_cast<SendFileHandle*>(it->second);
+
+ LOG(INFO) << "Emit signal to :" << handle->sender.c_str();
+
+ g_dbus_connection_emit_signal(handle->connection, handle->sender.c_str(),
+ kDBusObjectPath, kDBusInterfaceName,
+ "SendFileProgressChanged", gv, &error);
+ if (error) {
+ LOG(ERROR) << "Failed to send progress " << error->message;
+ g_error_free(error);
+ }
+}
+
bool DBusService::HandleDiscoverUnownedDevices(GVariant* params,
GDBusMethodInvocation* invocation) {
EventHandler().on_event();
}
bool DBusService::HandleSendFile(GVariant* params,
- GDBusMethodInvocation* invocation) {
+ GDBusMethodInvocation* invocation, const gchar* sender,
+ GDBusConnection* connection) {
LOG(INFO) << "HandleSendFile ";
gchar* device_id;
gchar* file_path;
LOG(INFO) << "To: " << device_id;
LOG(INFO) << "Path: " << file_path;
+ LOG(INFO) << "Sender: " << sender;
+
+ // To send file multiple devices in simultaneously, we can use
+ // key that conjunction with device_id and file_path.
+ // For now, mdg only allows one file at a time so we had to keep limitation.
+ if (file_map_.count(std::string(file_path)) > 0) {
+ // TODO(darrenh.jung) set real error code
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", -1));
+ return false;
+ }
+
+ SendFileHandle* handle = new SendFileHandle(std::string(file_path),
+ std::string(sender),
+ std::string(device_id),
+ reinterpret_cast<GDBusMethodInvocation*>(g_object_ref(invocation)),
+ reinterpret_cast<GDBusConnection*>(g_object_ref(connection)));
+
+ file_map_.emplace(handle->file_path, handle);
+
+ boost::optional<int> r =
+ EventHandler().send_file_event(handle->device_id, handle->file_path);
+
+ if (!r) {
+ LOG(ERROR) << "Failed to send file";
+ return false;
+ }
- EventHandler().send_file_event(device_id, file_path);
return true;
}
-void DBusService::HandleMethodCall(GDBusConnection* /* connection */,
- const gchar* /* sender */, const gchar* /* object_path */,
+void DBusService::HandleMethodCall(GDBusConnection* connection,
+ const gchar* sender, const gchar* /* object_path */,
const gchar* /* interface_name */, const gchar* method_name,
GVariant* parameters, GDBusMethodInvocation* invocation,
gpointer /* user_data */) {
HandleSendRemoteAppControl(parameters, invocation);
return;
} else if (g_strcmp0("SendFile", method_name) == 0) {
- HandleSendFile(parameters, invocation);
+ r = HandleSendFile(parameters, invocation, sender, connection);
return;
}
std::function<int(const std::string&, const unsigned char*,
size_t)> handler);
static void RegisterSendFileHandler(const std::string& method,
- std::function<bool(const std::string&, const std::string&)> handler);
+ std::function<int(const std::string&, const std::string&)> handler);
static void SendAppControlReply(int msg_id, const unsigned char* data,
size_t len);
+ static void SendFileResult(const std::string& file_path, int result);
+ static void SendFileProgress(const std::string& file_path,
+ int64_t send_size, int64_t total_size);
private:
class DBusMethodHandler {
boost::signals2::signal<void()> on_event2;
boost::signals2::signal<int(const std::string&, const unsigned char*,
size_t)> send_app_control_event;
- boost::signals2::signal<void(const std::string&,
+ boost::signals2::signal<int(const std::string&,
const std::string&)> send_file_event;
};
bool HandleSendRemoteAppControl(GVariant* params,
GDBusMethodInvocation* invocation);
bool HandleSendFile(GVariant* params,
- GDBusMethodInvocation* invocation);
+ GDBusMethodInvocation* invocation, const gchar* sender,
+ GDBusConnection* connection);
void HandleMethodCall(GDBusConnection* connection,
const gchar* sender, const gchar* object_path,
capmgr::DBusService::SendAppControlReply(msg_id, data, len);
}
-void SendFileProgressCb(const char* file_path, int64_t send_size,
+void SendFileProgressCb(const char* file_path_, int64_t send_size,
int64_t total_size, int percent, void* user_data) {
+ std::string file_path = std::string(file_path_);
LOG(INFO) << "SendFileProgressCb called. "
<< "file_path: " << file_path
<< "send_size: " << send_size
<< "total_size: " << total_size
<< "percent: " << percent;
+
+ capmgr::DBusService::SendFileProgress(file_path, send_size, total_size);
}
void SendFileFinishCb(int result, mdg_device_h device,
void* user_data) {
+ std::string& file_path = *static_cast<std::string*>(user_data);
LOG(INFO) << "SendFileFinishCb called. "
- << "result: " << result;
+ << "\nresult: " << result
+ << "\npath: " << file_path;
+
+ capmgr::DBusService::SendFileResult(file_path, result);
}
std::string GetDeviceIdFromHandle(const mdg_device_h device) {
return true;
}
-bool MDGManager::SendFile(const std::string& device_id,
+int MDGManager::SendFile(const std::string& device_id,
const std::string& file_path) {
LOG(INFO) << "SendFile to " << device_id;
LOG(INFO) << "File: " << file_path;
mdg_device_h device = GetDeviceHandleFromId(device_id);
if (!device) {
LOG(ERROR) << "There is no such device in list!";
- return false;
+ return -1;
}
int ret = mdg_device_send_file(mdg_handle_, device,
const_cast<char*>(file_path.c_str()), SendFileProgressCb,
- SendFileFinishCb, this);
+ SendFileFinishCb,
+ reinterpret_cast<void*>(const_cast<std::string*>(&file_path)));
if (ret != MDG_ERROR_NONE)
LOG(ERROR) << "Failed to send file: " << MDGErrorToString(ret);
- return true;
+ return 0;
}