--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef INCLUDE_CAPABILITY_MANAGER_INTERNAL_H_
+#define INCLUDE_CAPABILITY_MANAGER_INTERNAL_H_
+
+#include "include/capability-manager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct capmgr_file_s* capmgr_file_h;
+
+typedef int (*capmgr_file_finish_cb)(capmgr_file_h file,
+ int result, void* user_data);
+
+typedef int (*capmgr_file_progress_cb)(
+ capmgr_file_h file, int64_t sent_size, int64_t total_size,
+ void* user_data);
+
+/**
+ * @brief
+ */
+int capmgr_file_create(capmgr_file_h* file);
+
+/**
+ * @brief
+ */
+int capmgr_file_destroy(capmgr_file_h file);
+
+/**
+ * @brief
+ */
+int capmgr_file_set_device(capmgr_file_h file,
+ const capmgr_device_h device);
+
+/**
+ * @brief
+ */
+int capmgr_file_set_path(capmgr_file_h file,
+ const char* file_path);
+
+/**
+ * @brief
+ */
+int capmgr_file_set_finish_cb(capmgr_file_h file,
+ capmgr_file_finish_cb cb, void* user_data);
+
+/**
+ * @brief
+ */
+int capmgr_file_set_progress_cb(capmgr_file_h file,
+ capmgr_file_progress_cb cb, void* user_data);
+
+/**
+ * @brief
+ */
+int capmgr_file_send(capmgr_file_h file);
+
+/* TODO(darrenh.jung)
+int capmgr_file_abort(capmgr_file_h file);
+
+int capmgr_file_cleanup(capmgr_file_h file);
+
+int capmgr_file_resume(capmgr_file_h file);
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDE_CAPABILITY_MANAGER_INTERNAL_H_
%files devel
%{_includedir}/capability-manager.h
+%{_includedir}/capability-manager_internal.h
%{_libdir}/pkgconfig/%{name}.pc
%{_libdir}/lib%{name}.so
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <glib.h>
+
+#include <cstring>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "include/capability-manager.h"
+#include "include/capability-manager_internal.h"
+#include "src/dbus.h"
+#include "src/dbus_signal.h"
+#include "src/utils/logging.h"
+
+#define API __attribute__((visibility("default")))
+
+struct capmgr_finish_cb_s {
+ int (*callback)(capmgr_file_h, int, void*);
+ void* user_data;
+};
+
+struct capmgr_progress_cb_s {
+ int (*callback)(capmgr_file_h, int64_t, int64_t, void*);
+ void* user_data;
+};
+
+struct capmgr_file_s {
+ capmgr_device_h device;
+ char* path;
+ capmgr::DBusSignal* ds;
+ capmgr_finish_cb_s finish_cb;
+ capmgr_progress_cb_s progress_cb;
+};
+
+int __default_finish_cb(capmgr_file_h file, int result, void *user_data) {
+ LOG(DEBUG) << "finished with: " << result;
+ return 0;
+}
+
+int __default_progress_cb(capmgr_file_h file, int64_t sent_size,
+ int64_t total_size, void *user_data) {
+ LOG(DEBUG) << "progress: " << sent_size << "/" << total_size;
+ return 0;
+}
+
+API int capmgr_file_create(capmgr_file_h* file) {
+ if (!file)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ try {
+ capmgr_file_s* f = new capmgr_file_s();
+ capmgr_file_set_finish_cb(f, __default_finish_cb, nullptr);
+ capmgr_file_set_progress_cb(f, __default_progress_cb, nullptr);
+
+ *file = f;
+ } catch (const std::bad_alloc& e) {
+ LOG(ERROR) << e.what();
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+ }
+
+ return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_file_destroy(capmgr_file_h file) {
+ if (!file)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ capmgr_device_destroy(file->device);
+ free(file->path);
+ delete file->ds;
+ delete file;
+
+ return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_file_set_device(capmgr_file_h file,
+ const capmgr_device_h device) {
+ if (!file || !device)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ if (file->device)
+ capmgr_device_destroy(file->device);
+
+ int ret = capmgr_device_clone(device, &file->device);
+ if (ret != CAPMGR_ERROR_NONE)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+
+ return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_file_set_path(capmgr_file_h file,
+ const char* path) {
+ if (!file || !path)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ if (file->path)
+ free(file->path);
+
+ file->path = strdup(path);
+ if (!file->path)
+ return CAPMGR_ERROR_OUT_OF_MEMORY;
+
+ return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_file_set_finish_cb(capmgr_file_h file,
+ capmgr_file_finish_cb cb, void *user_data) {
+ if (!file)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ file->finish_cb.callback = cb;
+ file->finish_cb.user_data = user_data;
+
+ return CAPMGR_ERROR_NONE;
+}
+
+API int capmgr_file_set_progress_cb(capmgr_file_h file,
+ capmgr_file_progress_cb cb, void *user_data) {
+ if (!file)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ file->progress_cb.callback = cb;
+ file->progress_cb.user_data = user_data;
+
+ return CAPMGR_ERROR_NONE;
+}
+
+void capmgr_send_file_callback(GVariant* result, void* user_data) {
+ capmgr_file_h file = reinterpret_cast<capmgr_file_h>(user_data);
+ LOG(INFO) << "Send File Callback called: " << file->path;
+ delete file->ds;
+ file->ds = nullptr;
+
+ int r = 0;
+ g_variant_get(result, "(i)", &r);
+ LOG(DEBUG) << "result:" << r;
+ if (file->finish_cb.callback)
+ file->finish_cb.callback(file, r, file->finish_cb.user_data);
+}
+
+void capmgr_progress_callback(GVariant* param, void* user_data) {
+ capmgr_file_h file = reinterpret_cast<capmgr_file_h>(user_data);
+
+ gchar* file_path;
+ int64_t sent_size;
+ int64_t total_size;
+
+ g_variant_get(param, "(sxx)", &file_path, &sent_size, &total_size);
+ // file_path may key for search handlers for multiple file handling.
+
+ if (file->progress_cb.callback) {
+ file->progress_cb.callback(file, sent_size, total_size,
+ file->progress_cb.user_data);
+ }
+}
+
+API int capmgr_file_send(capmgr_file_h file) {
+ if (!file || !file->device || !file->path)
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+
+ int ret;
+ char* device_id;
+ ret = capmgr_device_get_device_id(file->device, &device_id);
+ if (ret != CAPMGR_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get device id";
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+
+ GVariant* gv = g_variant_new("(&s&s)", device_id, file->path);
+ if (!gv) {
+ LOG(ERROR) << "Failed to create GVariant";
+ free(device_id);
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+
+ file->ds = new capmgr::DBusSignal("SendFileProgressChanged");
+ file->ds->RegisterHandler(capmgr_progress_callback, file);
+ file->ds->Subscribe();
+
+ if (!capmgr::ProxyCallAsync("SendFile", gv, capmgr_send_file_callback,
+ file)) {
+ LOG(ERROR) << "Failed to dbus method call";
+ g_variant_unref(gv);
+ delete file->ds;
+ file->ds = nullptr;
+ free(device_id);
+ // errcode?
+ return CAPMGR_ERROR_INVALID_PARAMETER;
+ }
+
+ g_variant_unref(gv);
+ free(device_id);
+
+ return CAPMGR_ERROR_NONE;
+}
// found in the LICENSE file.
#include "src/dbus.h"
+#include "src/dbus_signal.h"
#include <glib.h>
#include <gio/gio.h>
delete cbdata;
}
-} // namespace
+void SignalCallback(GDBusProxy* proxy, gchar* sender_name, gchar* signal_name,
+ GVariant* parameters, gpointer user_data) {
+ capmgr::DBusSignal* ds = reinterpret_cast<capmgr::DBusSignal*>(user_data);
-namespace capmgr {
+ LOG(INFO) << "Signal recieved " << signal_name;
+ if (g_strcmp0(ds->GetSignalName(), signal_name) == 0) {
+ LOG(INFO) << "progress callback called";
+ ds->Emit(parameters);
+ }
+}
-bool ProxyCallAsync(const char* method, GVariant* params, DBusCallback cb,
- void* user_data) {
+bool InitDBusProxy(GDBusConnection** connection, GDBusProxy** proxy) {
GError* error = nullptr;
GDBusConnection* conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
- if (!conn || error) {
+ if (!conn) {
LOG(ERROR) << "g_bus_get_sync() failed: " << error->message;
+ g_object_unref(error);
return false;
}
- GDBusProxy* proxy = g_dbus_proxy_new_sync(conn,
+
+ GDBusProxy* p = g_dbus_proxy_new_sync(conn,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, nullptr,
kDBusServiceName, kDBusObjectPath, kDBusInterfaceName, nullptr,
&error);
- if (!proxy || error) {
+ if (!p) {
LOG(ERROR) << "g_dbus_proxy_new_sync() failed: " << error->message;
+ g_object_unref(error);
+ g_object_unref(conn);
+ return false;
+ }
+
+ *connection = conn;
+ *proxy = p;
+ return true;
+}
+
+void DisposeDBusProxy(GDBusConnection* conn, GDBusProxy* proxy) {
+ if (proxy)
+ g_object_unref(proxy);
+ if (conn) {
+ g_dbus_connection_flush_sync(conn, nullptr, nullptr);
g_object_unref(conn);
+ }
+}
+
+} // namespace
+
+namespace capmgr {
+
+DBusSignal::DBusSignal(const std::string& signal_name)
+ : signal_name_ { signal_name } {}
+
+DBusSignal::~DBusSignal() {
+ DisposeDBusProxy(this->conn_, this->proxy_);
+}
+
+void DBusSignal::RegisterHandler(DBusCallback cb, void* user_data) {
+ this->cb_ = cb;
+ this->user_data_ = user_data;
+}
+
+void DBusSignal::Emit(GVariant* param) {
+ this->cb_(param, this->user_data_);
+}
+
+bool DBusSignal::Subscribe() {
+ if (!InitDBusProxy(&this->conn_, &this->proxy_)) {
+ LOG(ERROR) << "DBus initilization failed";
+ return false;
+ }
+
+ g_signal_connect(this->proxy_, "g-signal", G_CALLBACK(SignalCallback), this);
+
+ return true;
+}
+
+const char* DBusSignal::GetSignalName() {
+ return this->signal_name_.c_str();
+}
+
+bool ProxyCallAsync(const char* method, GVariant* params, DBusCallback cb,
+ void* user_data) {
+ GDBusConnection* conn = nullptr;
+ GDBusProxy* proxy = nullptr;
+
+ if (!InitDBusProxy(&conn, &proxy)) {
+ LOG(ERROR) << "DBus initilization failed";
return false;
}
g_dbus_proxy_call(proxy, method,
params, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, MethodCallback, cbdata);
- g_object_unref(proxy);
- g_dbus_connection_flush_sync(conn, nullptr, nullptr);
- g_object_unref(conn);
+ DisposeDBusProxy(conn, proxy);
return true;
}
#define DBUS_H_
#include <glib.h>
+#include <gio/gio.h>
+
+#include <string>
#include "include/capability-manager.h"
--- /dev/null
+// Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef DBUS_SIGNAL_H_
+#define DBUS_SIGNAL_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <string>
+
+#include "src/dbus.h"
+
+namespace capmgr {
+
+class DBusSignal {
+ public:
+ explicit DBusSignal(const std::string& signal_name);
+ ~DBusSignal();
+ void RegisterHandler(DBusCallback cb, void* user_data);
+ bool Subscribe();
+ const char* GetSignalName();
+ void Emit(GVariant* param);
+
+ private:
+ std::string signal_name_;
+ DBusCallback cb_;
+ void* user_data_;
+ GDBusProxy* proxy_;
+ GDBusConnection* conn_;
+};
+
+} // namespace capmgr
+
+#endif // DBUS_SIGNAL_H_
#include <iostream>
#include "include/capability-manager.h"
+#include "include/capability-manager_internal.h"
namespace bpo = boost::program_options;
const capmgr_app_control_h reply, capmgr_app_control_result_e result,
void* user_data);
+ static int FileFinishCb(capmgr_file_h file, int result, void* user_data);
+ static int FileProgressCb(capmgr_file_h file,
+ int64_t sent_size, int64_t total_size, void* user_data);
+
GMainLoop* loop_;
GDBusConnection* conn_;
GDBusProxy* proxy_;
return;
}
- if (file_path.empty()) {
- std::cout << "File path is missing!" << std::endl;
+ capmgr_device_h device = nullptr;
+ struct cbdata cbdata = {&device, device_id};
+ int ret = capmgr_device_foreach_devices(DeviceForeachCb, &cbdata);
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_device_foreach_devices() failed: " << ret
+ << std::endl;
+ return;
+ }
+
+ if (*cbdata.device == nullptr) {
+ std::cout << "There is no such device!" << std::endl;
+ return;
+ }
+
+ capmgr_file_h file;
+ ret = capmgr_file_create(&file);
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_file_create() failed: " << ret << std::endl;
+ capmgr_device_destroy(device);
+ return;
+ }
+
+ ret = capmgr_file_set_device(file, device);
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_file_set_device() failed: " << ret
+ << std::endl;
+ capmgr_device_destroy(device);
+ capmgr_file_destroy(file);
+ return;
+ }
+
+ ret = capmgr_file_set_path(file, file_path.c_str());
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_file_set_path() failed: " << ret
+ << std::endl;
+ capmgr_device_destroy(device);
+ capmgr_file_destroy(file);
return;
}
- std::cout << "Send file " << file_path << " to " << device_id << std::endl;
+ ret = capmgr_file_set_finish_cb(file, FileFinishCb, this);
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_file_set_finish_cb() failed: " << ret
+ << std::endl;
+ capmgr_device_destroy(device);
+ capmgr_file_destroy(file);
+ return;
+ }
- GVariant* params = g_variant_new("(ss)", device_id.c_str(),
- file_path.c_str());
- if (!params) {
- std::cout << "out of memory" << std::endl;
+ ret = capmgr_file_set_progress_cb(file, FileProgressCb, this);
+ if (ret != CAPMGR_ERROR_NONE) {
+ std::cout << "capmgr_file_set_progress_cb() failed: " << ret
+ << std::endl;
+ capmgr_device_destroy(device);
+ capmgr_file_destroy(file);
return;
}
- GVariant* ret = ProxyCallSync("SendFile", params);
+ ret = capmgr_file_send(file);
+ if (ret != CAPMGR_ERROR_NONE)
+ std::cout << "capmgr_file_send failed: " << ret
+ << std::endl;
- g_object_unref(params);
- g_object_unref(ret);
+ capmgr_device_destroy(device);
+ WaitForResult();
}
GVariant* Client::ProxyCallSync(const char* method, GVariant* params) {
g_main_loop_quit(loop_);
}
+int Client::FileFinishCb(capmgr_file_h file,
+ int result, void* user_data) {
+ std::cout << "FileFinishCb called: " << result << std::endl;
+
+ capmgr_file_destroy(file);
+
+ Client* client = static_cast<Client*>(user_data);
+ client->Quit();
+ return 0;
+}
+
+int Client::FileProgressCb(capmgr_file_h file, int64_t sent_size,
+ int64_t total_size, void* user_data) {
+ std::cout << "FileProgressCb called ("
+ << sent_size << "/" << total_size << ")bytes sent" << std::endl;
+
+ return 0;
+}
+
int Client::AppControlCb(const capmgr_app_control_h request,
const capmgr_app_control_h reply, capmgr_app_control_result_e result,
void* user_data) {