MDGManager class is wrapper class using mdg APIs.
This class replace Iotivity class.
Change-Id: I30a2c980e82f0be73caecd468726571d8da5841a
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog)
PKG_CHECK_MODULES(GIO_DEPS REQUIRED gio-2.0)
PKG_CHECK_MODULES(GLIB_DEPS REQUIRED glib-2.0)
-PKG_CHECK_MODULES(IOTIVITY_DEPS REQUIRED iotivity)
PKG_CHECK_MODULES(JSONCPP_DEPS REQUIRED jsoncpp)
+PKG_CHECK_MODULES(MDG_DEPS REQUIRED capi-network-mdg)
PKG_CHECK_MODULES(PKGMGR_DEPS REQUIRED pkgmgr)
PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info)
PKG_CHECK_MODULES(SQLITE_DEPS REQUIRED sqlite3)
FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options)
FIND_PACKAGE(GTest REQUIRED)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/oic_svr_db_capmgr.dat DESTINATION ${SVR_DB_DIR})
-
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(tools)
-%define svr_db_dir %{TZ_SYS_GLOBALUSER_DATA}/capmgr
-%define svr_db_path %{svr_db_dir}/oic_svr_db_capmgr.dat
-
Name: capmgr
Summary: Capability Manager
Version: 0.0.1
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(gio-2.0)
BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(iotivity)
BuildRequires: pkgconfig(jsoncpp)
BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(capi-network-mdg)
BuildRequires: pkgconfig(pkgmgr)
BuildRequires: pkgconfig(pkgmgr-info)
BuildRequires: pkgconfig(sqlite3)
%build
MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
-%cmake . -DSVR_DB_DIR=%{svr_db_dir} \
- -DSVR_DB_PATH=%{svr_db_path} \
- -DUNITDIR=%{_unitdir} \
+%cmake . -DUNITDIR=%{_unitdir} \
-DFULLVER=%{version} \
-DMAJORVER=${MAJORVER}
/sbin/ldconfig
systemctl daemon-reload
-chsmack -a System %{svr_db_path}
-
%files
%manifest %{name}.manifest
%license LICENSE
%{_unitdir}/%{name}.service
%{_unitdir}/multi-user.target.wants/%{name}.service
-%defattr(-,app_fw,app_fw,-)
-%{svr_db_dir}
-%{svr_db_path}
-
%files tests
%{_bindir}/capmgr-ut/*
/opt/share/capmgr-ut/*
APPLY_PKG_CONFIG(${TARGET_CAPMGR} PUBLIC
DLOG_DEPS
GLIB_DEPS
- IOTIVITY_DEPS
)
TARGET_LINK_LIBRARIES(${TARGET_CAPMGR} PUBLIC ${TARGET_LIB_COMMON})
bool Capmgr::Initialize() {
cm_->LoadCapabilities();
connmgr_->RegisterEndpoint();
+ connmgr_->FindDevices();
DBusService::RegisterMethodHandler("DiscoverUnownedDevices", std::bind(
&ConnectionManager::FindDevices, connmgr_.get()));
// Use of this source code is governed by a apache 2.0 license that can be
// found in the LICENSE file.
-// iotivity headers should be included before boost headers...
-// this makes compilation warning. (redefinition)
-#include "common/iotivity.h"
#include "common/capability_manager.h"
#include "capmgr/capmgr.h"
#include "common/connection_manager.h"
#include "common/dbus_service.h"
+#include "common/mdg_manager.h"
#include "common/package_event_listener.h"
#include "common/utils/logging.h"
pkgmgr.SubscribePackageEvent();
capmgr::CapabilityManager* cm = new capmgr::CapabilityManager();
- capmgr::ConnectionManager* connmgr = new capmgr::Iotivity(cm);
+ capmgr::ConnectionManager* connmgr = new capmgr::MDGManager(cm);
capmgr::DBusService* dbus = new capmgr::DBusService();
capmgr::Capmgr capmgr(cm, connmgr, dbus);
if (!capmgr.Initialize()) {
DLOG_DEPS
GIO_DEPS
GLIB_DEPS
- IOTIVITY_DEPS
JSONCPP_DEPS
+ MDG_DEPS
PKGMGR_DEPS
PKGMGR_INFO_DEPS
SQLITE_DEPS
)
-ADD_DEFINITIONS("-DSVR_DB_DIR=\"${SVR_DB_DIR}\"")
-ADD_DEFINITIONS("-DSVR_DB_PATH=\"${SVR_DB_PATH}\"")
-ADD_DEFINITIONS("-DPM_DB_PATH=\"${SVR_DB_DIR}/pdm.db\"")
-
SET_TARGET_PROPERTIES(${TARGET_LIB_COMMON} PROPERTIES VERSION ${FULLVER})
SET_TARGET_PROPERTIES(${TARGET_LIB_COMMON} PROPERTIES SOVERSION ${MAJORVER})
std::string CapabilityManager::PackCapabilities() {
Json::Value root;
Json::Value caps;
+ LOG(INFO) << "Pack " << list_.size() << " capabilities";
for (const auto& cap : list_)
caps.append(cap.Serialize());
root["capabilities"] = caps;
list.emplace_back(caps[i].asString());
}
+ LOG(INFO) << "Unpacked " << list.size() << " capabilities";
+
return list;
}
" <arg type='v' name='result' direction='out'/>"
" </method>"
" <method name='SendRemoteAppControl'>"
- " <arg type='(sss)' name='appcontrol' direction='in'/>"
+ " <arg type='s' name='appcontrol' direction='in'/>"
+ " <arg type='s' name='appid' direction='in'/>"
+ " <arg type='s' name='pkgid' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
" </interface>"
gchar* name;
gchar* appid;
gchar* pkgid;
- g_variant_get(params, "((sss))", &name, &appid, &pkgid);
+ g_variant_get(params, "(sss)", &name, &appid, &pkgid);
Capability cap(name, pkgid, appid);
LOG(INFO) << "From: " << cap.name();
boost::signals2::signal<bool(Capability*, AppControlHandler)>
send_app_control_event;
boost::signals2::signal<void(GVariant**)> get_remote_caps_event;
+ boost::signals2::signal<void(char* data)> send_data_event;
};
static DBusMethodHandler& EventHandler() {
+++ /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 "common/iotivity.h"
-
-#include <octypes.h>
-#include <pmtypes.h>
-#include <OCPlatform.h>
-
-#include <boost/algorithm/string/replace.hpp>
-#include <OCProvisioningManager.hpp>
-
-#include <functional>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "common/capability.h"
-#include "common/capability_manager.h"
-#include "common/appcontrol_manager.h"
-#include "common/utils/logging.h"
-
-namespace {
-
-const int kDiscoverTimeoutSec = 5;
-const int kUUIDLength = UUID_LENGTH;
-const char kResourceTypeName[] = "capmgr.capabilities";
-
-FILE* ServerFopen(const char* /* unused */, const char* mode) {
- return fopen(SVR_DB_PATH, mode);
-}
-
-std::string ConvertUUIDtoString(const OicUuid_t& uuid) {
- std::ostringstream oss;
- for (int i = 0; i < kUUIDLength; i++)
- oss << uuid.id[i];
- return oss.str();
-}
-
-void OtmEventCb(void* /* ctx */, const char* addr, uint16_t port,
- const char* owner_id, OCOtmEvent_t event) {
- LOG(INFO) << "Get OTM Event";
- LOG(INFO) << "Addr: " << addr;
- LOG(INFO) << "owner_id: " << owner_id;
- switch (event) {
- case OC_OTM_READY:
- LOG(INFO) << "OC_OTM_READY";
- break;
- case OC_OTM_STARTED:
- LOG(INFO) << "OC_OTM_STARTED";
- break;
- case OC_OTM_DONE:
- LOG(INFO) << "OC_OTM_DONE";
- break;
- case OC_OTM_ERROR:
- LOG(INFO) << "OC_OTM_ERROR";
- break;
- default:
- LOG(ERROR) << "Unknown OTM event";
- break;
- }
-}
-
-} // namespace
-
-namespace capmgr {
-
-Iotivity::Iotivity(CapabilityManager* capmgr) : ConnectionManager(capmgr) {
- OCSetOtmEventHandler(nullptr, OtmEventCb);
-
- ps_ = {
- ServerFopen, fread, fwrite, fclose, unlink, nullptr, nullptr
- };
-
- OC::PlatformConfig config = OC::PlatformConfig {
- OC::ServiceType::InProc,
- OC::ModeType::Both,
- "0.0.0.0",
- 0,
- OC::QualityOfService::LowQos,
- &ps_
- };
-
- OC::OCPlatform::Configure(config);
-/*
- OCStackResult result = SetPlatformInfo(kPlatformId, kManufactureName,
- kManufacturerLink, kModelNumber, kDateOfManufacture, kPlatformVersion,
- kOperatingSystemVersion, kHardwareVersion, kFirmwareVersion, kSupportLink,
- kSystemTime);
- result = OCPlatform::registerPlatformInfo(platformInfo);
-*/
-}
-Iotivity::~Iotivity() {
-}
-
-void Iotivity::FindDevices() {
- DiscoverUnownedDevices();
-}
-
-void Iotivity::RegisterEndpoint() {
- RegisterResource();
-}
-
-void Iotivity::ExchangeCapabilities() {
- for (const auto& it : resource_list_)
- GetResource(it.second);
-}
-
-bool Iotivity::SendCapability(Capability* cap,
- std::function<void(Capability, int)> reply) {
- PutResource(cap, reply);
- return 0;
-}
-
-void Iotivity::PutResource(Capability* cap,
- std::function<void(Capability, int)> putCallback) {
- LOG(INFO) << "Put Resource";
- for (const auto& it : resource_list_) {
- std::shared_ptr<OC::OCResource> resource;
- resource = it.second;
- OC::OCRepresentation rep;
-
- LOG(INFO) << "Putting.." << resource->uri();
- rep.setValue("capability", cap->Serialize());
-
- Capability dup(cap->name(), cap->pkgid(), cap->appid());
- OC::QueryParamsMap queryParamsMap;
- OCStackResult res = resource->put(rep, queryParamsMap,
- [=](const OC::HeaderOptions& opts, const OC::OCRepresentation& rep,
- const int ec) {
- LOG(INFO) << "From: " << rep.getUri() << " of " << rep.getHost();
- LOG(INFO) << "PUT RESULT data: " << ec;
-
- putCallback(dup, ec);
- });
-
- LOG(INFO) << "res: " << res;
- }
-}
-
-void Iotivity::RegisterResource() {
- std::string uri = "/capmgr/capabilities";
- uint8_t property = OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE;
-
- OCStackResult result = OC::OCPlatform::registerResource(resource_,
- uri, kResourceTypeName, OC::DEFAULT_INTERFACE,
- std::bind(&Iotivity::EntityCb, this, std::placeholders::_1),
- property);
- if (result != OC_STACK_OK)
- LOG(ERROR) << "OCPlatform::registerResource() failed: " << result;
-
- LOG(INFO) << "Registered as: " << uri;
-}
-
-void Iotivity::FindResource(const std::string& addr) {
- OCStackResult result = OC::OCPlatform::findResource(
- !addr.empty() ? addr : "", OC_RSRVD_WELL_KNOWN_URI,
- CT_DEFAULT, std::bind(&Iotivity::FindCb, this, std::placeholders::_1));
- if (result != OC_STACK_OK)
- LOG(ERROR) << "OCPlatform::findResource() failed: " << result;
-}
-
-void Iotivity::DiscoverUnownedDevices() {
- if (OC::OCSecure::provisionInit(PM_DB_PATH) != OC_STACK_OK)
- LOG(ERROR) << "provisionInit() failed!";
-
- unowned_dev_list_.clear();
- OCStackResult result =
- OC::OCSecure::discoverUnownedDevices(kDiscoverTimeoutSec,
- unowned_dev_list_);
-
- if (result != OC_STACK_OK)
- LOG(ERROR) << "discoverUnownedDevices() failed: " << result;
- else
- LOG(INFO) << "Discovered " << unowned_dev_list_.size()
- << " unowned devices";
-
- OwnershipTransfer();
-}
-
-void Iotivity::OwnershipTransfer() {
- for (const auto& sec_rsc : unowned_dev_list_) {
- // get IPv6 address
- std::string devaddr = sec_rsc->getDevAddr();
- // percent-encoding
- boost::replace_all(devaddr, "%", "%25");
- std::ostringstream oss;
- oss << "coaps://[" << devaddr << "]:" << sec_rsc->getDevPtr()->securePort;
- devaddr = oss.str();
-
- LOG(INFO) << "Do ownership transfer. Address: " << devaddr << ", DeviceID: "
- << sec_rsc->getDeviceID();
-
- sec_rsc->doOwnershipTransfer(
- [this, devaddr](OC::PMResultList_t* result, int hasError) {
- if (hasError) {
- LOG(ERROR) << "Failed to ownership transfer :: " << hasError;
- return;
- }
- LOG(INFO) << "Ownership transferred: "
- << ConvertUUIDtoString(result->at(0).deviceId);
- FindResource(devaddr);
- });
- }
-}
-
-void Iotivity::GetResource(std::shared_ptr<OC::OCResource> resource) {
- std::string hostaddr = resource->host();
- // empty QueryParams
- OC::QueryParamsMap qmap;
- resource->get(qmap,
- [this, hostaddr](const OC::HeaderOptions& opts,
- const OC::OCRepresentation& rep, const int ec) {
- if (ec != OC_STACK_OK) {
- LOG(ERROR) << "GET error";
- return;
- }
-
- std::string data;
- rep.getValue("data", data);
-
- LOG(INFO) << "From: " << rep.getUri() << " of " << rep.getHost();
- LOG(INFO) << "Get RESULT data: " << data;
-
- // for debug
- std::vector<Capability> caps = capmgr_->UnpackCapabilities(data);
- for (const auto& cap : caps)
- LOG(INFO) << "1: " << cap.name() << ", 2: " << cap.pkgid()
- << ", 3: " << cap.appid();
- });
-}
-
-OCEntityHandlerResult Iotivity::EntityCb(
- std::shared_ptr<OC::OCResourceRequest> request) {
- LOG(DEBUG) << "entity cb";
- if (!request) {
- LOG(ERROR) << "Invalid OC request";
- return OC_EH_ERROR;
- }
-
- std::string req_type = request->getRequestType();
- if (req_type == "GET") {
- LOG(WARNING) << "The request is GET";
-
- // OC::QueryParamsMap qmap = request->getQueryParameters();
-
- OC::OCRepresentation rep;
- rep.setUri("/capmgr/capabilities");
- std::string capabilities = capmgr_->PackCapabilities();
- rep.setValue("data", capabilities);
-
- auto response = std::make_shared<OC::OCResourceResponse>();
- response->setErrorCode(200); // ??
- response->setResponseResult(OC_EH_OK);
- response->setResourceRepresentation(rep);
- response->setRequestHandle(request->getRequestHandle());
- response->setResourceHandle(request->getResourceHandle());
-
- OCStackResult result = OC::OCPlatform::sendResponse(response);
- if (result != OC_STACK_OK)
- LOG(ERROR) << "OCPlatform::sendResponse() error: " << result;
- else
- LOG(INFO) << "Sending response done";
-
- return OC_EH_OK;
- }
-
- if (req_type == "PUT") {
- LOG(WARNING) << "The request is PUT";
- OC::OCRepresentation rep = request->getResourceRepresentation();
- int ret;
-
- std::string cap_data;
- rep.getValue("capability", cap_data);
- LOG(INFO) << "capability : " << cap_data;
-
- Capability cap(cap_data);
-
- ret = AppControlManager::LaunchApplication(cap);
- if (ret != 0) {
- return OC_EH_ERROR;
- }
-
- return OC_EH_OK;
- }
-
- return OC_EH_OK;
-}
-
-void Iotivity::FindCb(std::shared_ptr<OC::OCResource> resource) {
- if (!resource) {
- LOG(ERROR) << "Invalid resource discovered";
- return;
- }
-
- if (resource_list_.find(resource->uniqueIdentifier()) !=
- resource_list_.end()) {
- LOG(DEBUG) << "Already discovered. Skip this resource";
- return;
- }
-
- LOG(INFO) << "Resource discovered: " << resource->uri()
- << ", id: " << resource->uniqueIdentifier()
- << ", host: " << resource->host();
- if (resource->uri().find("capmgr") != std::string::npos) {
- LOG(INFO) << "Found capability resource";
- resource_list_[resource->uniqueIdentifier()] = resource;
- GetResource(resource);
- }
-}
-
-} // namespace capmgr
+++ /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 COMMON_IOTIVITY_H_
-#define COMMON_IOTIVITY_H_
-
-#include <octypes.h>
-#include <pmtypes.h>
-#include <OCApi.h>
-#include <OCPlatform.h>
-
-#include <OCProvisioningManager.hpp>
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "common/connection_manager.h"
-
-namespace capmgr {
-
-class CapabilityManager;
-
-class Iotivity : public ConnectionManager {
- public:
- explicit Iotivity(CapabilityManager* capmgr);
- ~Iotivity();
-
- void FindDevices() override;
- void RegisterEndpoint() override;
- void ExchangeCapabilities() override;
- bool SendCapability(
- Capability* cap, std::function<void(Capability, int)> reply) override;
-
- private:
- void RegisterResource();
- void FindResource(const std::string& addr);
- void PutResource(
- Capability* cap, std::function<void(Capability, int)> putCallback);
- void DiscoverUnownedDevices();
- void OwnershipTransfer();
- void GetResource(std::shared_ptr<OC::OCResource> resource);
- OCEntityHandlerResult EntityCb(
- std::shared_ptr<OC::OCResourceRequest> request);
- void FindCb(std::shared_ptr<OC::OCResource> resource);
-
- OCPersistentStorage ps_;
- OCResourceHandle resource_;
- std::map<OC::OCResourceIdentifier, std::shared_ptr<OC::OCResource>>
- resource_list_;
- OC::DeviceList_t unowned_dev_list_;
-};
-
-} // namespace capmgr
-
-#endif // COMMON_IOTIVITY_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.
+
+#include "common/mdg_manager.h"
+
+#include <glib.h>
+#include <mdg.h>
+#include <mdg_internal.h>
+
+#include <cstring>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/appcontrol_manager.h"
+#include "common/capability.h"
+#include "common/capability_manager.h"
+#include "common/utils/glist_range.h"
+#include "common/utils/logging.h"
+
+namespace {
+
+const int kRequestTimeout = 5;
+const char kGroupName[] = "capmgrgroup";
+const char kPIN[] = "12341234";
+const std::map<int, std::string> kMDGErrorString = {
+ {MDG_ERROR_NONE, "MDG_ERROR_NONE"},
+ {MDG_ERROR_IO_ERROR, "MDG_ERROR_IO_ERROR"},
+ {MDG_ERROR_INVALID_PARAMETER, "MDG_ERROR_INVALID_PARAMETER"},
+ {MDG_ERROR_OUT_OF_MEMORY, "MDG_ERROR_OUT_OF_MEMORY"},
+ {MDG_ERROR_PERMISSION_DENIED, "MDG_ERROR_PERMISSION_DENIED"},
+ {MDG_ERROR_NOT_SUPPORTED, "MDG_ERROR_NOT_SUPPORTED"},
+ {MDG_ERROR_NO_DATA, "MDG_ERROR_NO_DATA"},
+ {MDG_ERROR_OPERATION_FAILED, "MDG_ERROR_OPERATION_FAILED"},
+ {MDG_ERROR_ALREADY_REGISTERED, "MDG_ERROR_ALREADY_REGISTERED"},
+ {MDG_ERROR_IN_PROGRESS, "MDG_ERROR_IN_PROGRESS"},
+ {MDG_ERROR_COMM_ERROR, "MDG_ERROR_COMM_ERROR"},
+ {MDG_ERROR_RX, "MDG_ERROR_RX"},
+ {MDG_ERROR_TX, "MDG_ERROR_TX"},
+ {MDG_ERROR_PLUGIN_FAIL, "MDG_ERROR_PLUGIN_FAIL"},
+ {MDG_ERROR_ALREADY_IN_PROGRESS, "MDG_ERROR_ALREADY_IN_PROGRESS"},
+ {MDG_ERROR_NOT_STARTED, "MDG_ERROR_NOT_STARTED"},
+ {MDG_ERROR_ALREADY_INITIALIZED, "MDG_ERROR_ALREADY_INITIALIZED"},
+};
+const char kSendDataCmd[] = "MDGD_REQ_SEND_DATA";
+
+std::string MDGErrorToString(int error) {
+ auto it = kMDGErrorString.find(error);
+ if (it == kMDGErrorString.end())
+ return "MDG_ERROR_UNKNOWN";
+ else
+ return it->second;
+}
+
+void SendDataFinishCb(int result, char *resp_data, void* user_data) {
+ LOG(INFO) << "SendDataFinishCb called."
+ << "result: " << result
+ << ", resp_data: " << resp_data;
+}
+
+} // namespace
+
+namespace capmgr {
+
+MDGManager::MDGManager(CapabilityManager* capmgr)
+ : ConnectionManager(capmgr), mdg_handle_(nullptr), device_list_(nullptr),
+ group_list_(nullptr) {
+ if (!Initialize())
+ LOG(ERROR) << "Failed to initialize";
+}
+
+MDGManager::~MDGManager() {}
+
+bool MDGManager::Initialize() {
+ int ret = mdg_initialize(&mdg_handle_);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to initialize mdg: " << MDGErrorToString(ret);
+ return false;
+ }
+
+ ret = mdg_request_result_callback(mdg_handle_, &MDGManager::RequestCb, this);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to set request result callback: "
+ << MDGErrorToString(ret);
+ return false;
+ }
+
+ ret = mdg_device_monitor_start(mdg_handle_, &MDGManager::DeviceMonitorCb,
+ this);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to start device monitoring: "
+ << MDGErrorToString(ret);
+ return false;
+ }
+
+ return true;
+}
+
+void MDGManager::RequestCb(char* cmd, char* device_id, unsigned char* arg,
+ int len, int ret, void* user_data) {
+ LOG(INFO) << "RequestCb called. "
+ << "cmd: " << cmd
+ << ", device_id: " << device_id
+ << ", ret: " << ret;
+
+ MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+ if (!strcmp(cmd, kSendDataCmd)) {
+ Command cmd;
+ memcpy(&cmd, arg, sizeof(unsigned char));
+ unsigned char* p = arg + sizeof(unsigned char);
+ if (cmd == Command::EXCHANGE_CAPS) {
+ std::string caps_str = std::string(reinterpret_cast<char*>(p));
+ std::vector<Capability> caps =
+ mdgmgr->capmgr_->UnpackCapabilities(caps_str);
+ LOG(INFO) << "Received " << caps.size() << " capabilities from device "
+ << device_id;
+ } else if (cmd == Command::SEND_CAP) {
+ std::string cap_str = std::string(reinterpret_cast<char*>(p));
+ Capability cap(cap_str);
+ int r = AppControlManager::LaunchApplication(cap);
+ if (r != 0)
+ LOG(ERROR) << "Failed to launch application: " << ret;
+ }
+ }
+}
+
+void MDGManager::DeviceMonitorCb(char* uuid, char* group_name,
+ mdg_device_status_e status, void* user_data) {
+ LOG(INFO) << "Device monitored! uuid: " << uuid
+ << ", group_name: " << group_name
+ << ", status: " << status;
+}
+
+bool MDGManager::GroupFoundCb(mdg_group_type_e type, mdg_group_h group,
+ void* user_data) {
+ char* group_name;
+ int ret = mdg_group_info_get_name(group, &group_name);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get group name: " << MDGErrorToString(ret);
+ return false;
+ }
+ char* group_addr;
+ ret = mdg_group_info_get_host_addr(group, &group_addr);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get group host addr: " << MDGErrorToString(ret);
+ free(group_name);
+ return false;
+ }
+
+ if (type == MDG_GROUP_TYPE_MINE)
+ LOG(INFO) << "Found group type MINE: " << group_name;
+ else
+ LOG(INFO) << "Found group type REMOTE: " << group_name
+ << " (" << group_addr << ")";
+
+ // need to check dup;
+ MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+ mdgmgr->group_list_ = g_list_append(mdgmgr->group_list_, group);
+
+ free(group_addr);
+ free(group_name);
+
+ return true;
+}
+
+void MDGManager::GroupFinishCb(int result, void* user_data) {
+ LOG(INFO) << "Find group finished: " << result;
+ int ret;
+ MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+ // TODO(jeremy.jang): too complicated. need to refactor.
+ for (auto& group : GListRange<mdg_group_h>(mdgmgr->group_list_)) {
+ char* group_name;
+ ret = mdg_group_info_get_name(group, &group_name);
+ if (ret != MDG_ERROR_NONE)
+ continue;
+ if (strcmp(group_name, kGroupName)) {
+ free(group_name);
+ continue;
+ }
+
+ mdg_group_type_e group_type;
+ ret = mdg_group_info_get_type(group, &group_type);
+ if (ret != MDG_ERROR_NONE)
+ continue;
+ // if group is mine, we don't need to join
+ if (group_type == MDG_GROUP_TYPE_MINE) {
+ LOG(INFO) << "Found my group. I'm the owner device";
+ return;
+ }
+
+ char* group_addr;
+ ret = mdg_group_info_get_host_addr(group, &group_addr);
+ if (ret != MDG_ERROR_NONE) {
+ free(group_name);
+ continue;
+ }
+ // request join group (request invite)
+ mdg_device_h owner_device = nullptr;
+ for (auto& device : GListRange<mdg_device_h>(mdgmgr->device_list_)) {
+ char* device_ip;
+ int ret = mdg_device_info_get_ip(device, &device_ip);
+ if (ret != MDG_ERROR_NONE)
+ continue;
+ // request to group owner only
+ // to compare ipv6 address only, discard first 8 chars of gruop_addr:
+ // format of group_addr: coap://[fe80::ae5a:14ff:fe24:b84e%25wlan0]:38720
+ if (!strncmp(group_addr + 8, device_ip, 25)) {
+ owner_device = device;
+ free(device_ip);
+ break;
+ }
+ free(device_ip);
+ }
+ free(group_addr);
+
+ if (!owner_device) {
+ LOG(ERROR) << "Cannot request invite. Cannot find proper device";
+ return;
+ }
+
+ ret = mdg_request_invite_device(mdgmgr->mdg_handle_, group, owner_device,
+ const_cast<char*>(kPIN), nullptr, nullptr);
+ if (ret == MDG_ERROR_NONE) {
+ LOG(INFO) << "Request to owner device to joining group";
+ return;
+ }
+ }
+
+ LOG(INFO) << "Group not found. Create one";
+ ret = mdg_group_create(mdgmgr->mdg_handle_, const_cast<char*>(kGroupName));
+ if (ret != MDG_ERROR_NONE)
+ LOG(ERROR) << "Failed to create group: " << ret;
+}
+
+bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
+ mdg_device_type_e device_type;
+ char* device_id;
+ char* device_ip;
+ char* model_name;
+
+ int ret = mdg_device_info_get_device_type(device, &device_type);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
+ return true;
+ }
+
+ ret = mdg_device_info_get_device_id(device, &device_id);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
+ return true;
+ }
+
+ ret = mdg_device_info_get_ip(device, &device_ip);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
+ free(device_id);
+ return true;
+ }
+
+ ret = mdg_device_info_get_model_name(device, &model_name);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
+ free(device_ip);
+ free(device_id);
+ return true;
+ }
+
+ LOG(INFO) << "Found device. "
+ << "device_id: " << device_id
+ << ", device_ip: " << device_ip
+ << ", model_name: " << model_name;
+
+ // need to check dup;
+ MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+ mdgmgr->device_list_ = g_list_append(mdgmgr->device_list_, device);
+
+ free(model_name);
+ free(device_ip);
+ free(device_id);
+
+ return true;
+}
+
+void MDGManager::DeviceFinishCb(int result, void* user_data) {
+ LOG(INFO) << "Find device finished: " << result;
+ MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+ mdgmgr->CreateOrJoinGroup();
+}
+
+bool MDGManager::CreateOrJoinGroup() {
+ int ret = mdg_group_find(mdg_handle_, kRequestTimeout,
+ &MDGManager::GroupFoundCb, &MDGManager::GroupFinishCb, this);
+ if (ret != MDG_ERROR_NONE) {
+ LOG(ERROR) << "Failed to find group: " << MDGErrorToString(ret);
+ return false;
+ }
+
+ return true;
+}
+
+bool MDGManager::SendData(Command cmd, const std::string& data) {
+ if (!g_list_length(device_list_)) {
+ LOG(ERROR) << "No device in list!";
+ return false;
+ }
+
+ size_t datasize = sizeof(Command) + data.size();
+ unsigned char* buf = new unsigned char[datasize];
+ unsigned char* p = buf;
+
+ memcpy(p, &cmd, sizeof(Command));
+ p = p + sizeof(Command);
+ memcpy(p, data.c_str(), data.size());
+ for (auto& device : GListRange<mdg_device_h>(device_list_)) {
+ int ret = mdg_device_send_data(mdg_handle_, device,
+ buf, datasize, SendDataFinishCb, this);
+ if (ret != MDG_ERROR_NONE)
+ LOG(ERROR) << "Failed to send data: " << MDGErrorToString(ret);
+ }
+
+ delete buf;
+
+ return true;
+}
+
+void MDGManager::FindDevices() {
+ int ret = mdg_device_find(mdg_handle_, kRequestTimeout,
+ &MDGManager::DeviceFoundCb, &MDGManager::DeviceFinishCb, this);
+ if (ret != MDG_ERROR_NONE)
+ LOG(ERROR) << "Failed to find device: " << MDGErrorToString(ret);
+}
+
+void MDGManager::RegisterEndpoint() {
+}
+
+void MDGManager::ExchangeCapabilities() {
+ std::string caps = capmgr_->PackCapabilities();
+ SendData(Command::EXCHANGE_CAPS, caps);
+}
+
+bool MDGManager::SendCapability(Capability* cap,
+ std::function<void(Capability, int)> reply) {
+ std::string cap_str = cap->Serialize();
+ return SendData(Command::SEND_CAP, cap_str);
+}
+
+} // namespace capmgr
--- /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 COMMON_MDG_MANAGER_H_
+#define COMMON_MDG_MANAGER_H_
+
+#include <glib.h>
+#include <mdg.h>
+
+#include <functional>
+#include <string>
+
+#include "common/connection_manager.h"
+
+namespace capmgr {
+
+class CapabilityManager;
+class Capability;
+
+class MDGManager : public ConnectionManager {
+ public:
+ explicit MDGManager(CapabilityManager* capmgr);
+ ~MDGManager();
+
+ void FindDevices() override;
+ void RegisterEndpoint() override;
+ void ExchangeCapabilities() override;
+ bool SendCapability(
+ Capability* cap, std::function<void(Capability, int)> reply) override;
+
+ private:
+ enum class Command : unsigned char {
+ EXCHANGE_CAPS,
+ SEND_CAP,
+ };
+
+ bool Initialize();
+ bool CreateOrJoinGroup();
+ bool SendData(Command cmd, const std::string& data);
+
+ static void RequestCb(char* cmd, char* device_id, unsigned char* arg,
+ int len, int ret, void* user_data);
+ static void DeviceMonitorCb(char* uuid, char* group_name,
+ mdg_device_status_e status, void* user_data);
+ static bool GroupFoundCb(mdg_group_type_e type, mdg_group_h group,
+ void* user_data);
+ static void GroupFinishCb(int result, void* user_data);
+ static bool DeviceFoundCb(mdg_device_h device, void* user_data);
+ static void DeviceFinishCb(int result, void* user_data);
+
+ mdg_h mdg_handle_;
+ GList* device_list_;
+ GList* group_list_;
+};
+
+} // namespace capmgr
+
+#endif // COMMON_MDG_MANAGER_H_
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_GLIST_RANGE_H_
+#define COMMON_UTILS_GLIST_RANGE_H_
+
+#include <glib.h>
+
+#include <cstddef>
+#include <iterator>
+
+// Range with mutable forward iterator based on GList
+// supporting language foreach construct
+template<typename T>
+class GListRange {
+ public:
+ class Iterator {
+ public:
+ typedef T value_type;
+ typedef T& reference;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef std::size_t difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ explicit Iterator(std::nullptr_t ptr = nullptr) : ptr_(ptr) { }
+ explicit Iterator(GList* ptr) : ptr_(ptr) { }
+ explicit operator bool() const {
+ return ptr_;
+ }
+ const reference& operator*() const {
+ return reinterpret_cast<const T&>(ptr_->data);
+ }
+ reference& operator*() {
+ return reinterpret_cast<T&>(ptr_->data);
+ }
+ const_pointer operator->() const {
+ return reinterpret_cast<pointer>(&ptr_->data);
+ }
+ pointer operator->() {
+ return reinterpret_cast<pointer>(&ptr_->data);
+ }
+ Iterator& operator++() {
+ ptr_ = g_list_next(ptr_);
+ return *this;
+ }
+ Iterator operator++(int) {
+ Iterator iter(ptr_);
+ ptr_ = g_list_next(ptr_);
+ return iter;
+ }
+ bool operator==(const Iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const Iterator& other) const {
+ return !this->operator==(other);
+ }
+
+ private:
+ GList* ptr_;
+ };
+
+ explicit GListRange(GList* list) : list_(list) { }
+ Iterator begin() {
+ return Iterator(list_);
+ }
+ Iterator end() {
+ return Iterator();
+ }
+
+ bool Empty() const noexcept {
+ return !list_;
+ }
+
+ guint Size() const {
+ return g_list_length(list_);
+ }
+
+ private:
+ GList* list_;
+};
+
+#endif // COMMON_UTILS_GLIST_RANGE_H_