Fix group invite logic
authorSangyoon Jang <jeremy.jang@samsung.com>
Mon, 23 Jul 2018 07:17:33 +0000 (16:17 +0900)
committer장상윤/Tizen Platform Lab(SR)/Engineer/삼성전자 <jeremy.jang@samsung.com>
Thu, 26 Jul 2018 05:10:55 +0000 (14:10 +0900)
- Register capmgr channel.
- Each capmgr will invite other devices.

Change-Id: Ie207728eacda32cdb5e0be1f47ab002156fc057e
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/capmgr/capmgr.cc
src/common/mdg_manager.cc
src/common/mdg_manager.h

index 5f2f4aa5b6cb717b0a937f24891ecb674d783200..b7522780885bf12524e8d2aa8e1d9407df309bd9 100644 (file)
@@ -69,7 +69,6 @@ Capmgr::~Capmgr() {
 bool Capmgr::Initialize() {
   cm_->LoadCapabilities();
   connmgr_->RegisterEndpoint();
-  connmgr_->FindDevices();
 
   DBusService::RegisterMethodHandler("DiscoverUnownedDevices", std::bind(
       &ConnectionManager::FindDevices, connmgr_.get()));
index 6a114b9c27eaffd2b9482a5ed5f580ca957ca6e7..855257de22f1e8e1dea964e33098b94ebe4fe2bc 100644 (file)
@@ -8,9 +8,11 @@
 #include <mdg.h>
 #include <mdg_internal.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <cstring>
 #include <map>
+#include <mutex>
 #include <string>
 #include <vector>
 
@@ -24,6 +26,7 @@
 namespace {
 
 const int kRequestTimeout = 5;
+const int kRequestWaitingSec = 1;
 const char kGroupName[] = "capmgrgroup";
 const char kChannelId[] = "capmgrchannel";
 const char kPIN[] = "12341234";
@@ -56,7 +59,7 @@ std::string MDGErrorToString(int error) {
 }
 
 void SendDataFinishCb(int result, void* user_data) {
-  LOG(INFO) << "SendDataFinishCb called."
+  LOG(INFO) << "SendDataFinishCb called. "
             << "result: " << result;
 }
 
@@ -65,8 +68,8 @@ void SendDataFinishCb(int result, void* user_data) {
 namespace capmgr {
 
 MDGManager::MDGManager(CapabilityManager* capmgr)
-  : ConnectionManager(capmgr), mdg_handle_(nullptr), device_list_(nullptr),
-    group_list_(nullptr) {
+  : ConnectionManager(capmgr), mdg_handle_(nullptr), group_handle_(nullptr),
+    device_list_(nullptr) {
   if (!Initialize())
     LOG(ERROR) << "Failed to initialize";
 }
@@ -80,151 +83,177 @@ bool MDGManager::Initialize() {
     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);
+  if (!CreateGroup()) {
+    LOG(ERROR) << "Failed to create capmgr group";
     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
+void MDGManager::ChannelCb(int result, char* device_id, char* channel_id,
+    unsigned char* arg, int len, void* user_data) {
+  LOG(INFO) << "ChannelCb called. "
+            << "result: " << result
             << ", device_id: " << device_id
-            << ", ret: " << ret;
+            << ", channel_id: " << channel_id
+            << ", len: " << len;
 
   MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
-  if (!strcmp(cmd, kSendDataCmd)) {
-    unsigned char* p = arg;
-    Command cmd;
-    memcpy(&cmd, p, sizeof(Command));
-    p = p + sizeof(Command);
-    size_t datasize;
-    memcpy(&datasize, p, sizeof(size_t));
-    p = p + sizeof(size_t);
-    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;
-      RemoteDeviceManager::RegisterRemoteDevice(device_id, caps);
-    } else if (cmd == Command::SEND_APPCONTROL) {
-      unsigned char* data = p;
-      int r = AppControlManager::LaunchApplication(data, datasize);
-      if (r != 0)
-        LOG(ERROR) << "Failed to launch application: " << ret;
-    }
+  unsigned char* p = arg;
+  Command cmd;
+  memcpy(&cmd, p, sizeof(Command));
+  p = p + sizeof(Command);
+  size_t datasize;
+  memcpy(&datasize, p, sizeof(size_t));
+  p = p + sizeof(size_t);
+  if (cmd == Command::EXCHANGE_CAPS) {
+    // including terminating null byte
+    char* caps_raw = new char[datasize + 1];
+    memcpy(caps_raw, p, datasize);
+    caps_raw[datasize] = '\0';
+    std::string caps_str = std::string(caps_raw);
+    delete caps_raw;
+    std::vector<Capability> caps =
+        mdgmgr->capmgr_->UnpackCapabilities(caps_str);
+    LOG(INFO) << "Received " << caps.size() << " capabilities from device "
+              << device_id;
+    RemoteDeviceManager::RegisterRemoteDevice(device_id, caps);
+  } else if (cmd == Command::SEND_APPCONTROL) {
+    unsigned char* data = p;
+    int r = AppControlManager::LaunchApplication(data, datasize);
+    if (r != 0)
+      LOG(ERROR) << "Failed to launch application: " << r;
   }
 }
 
 bool MDGManager::GroupFoundCb(mdg_group_type_e type, mdg_group_h group,
     void* user_data) {
+  if (type != MDG_GROUP_TYPE_LOCAL)
+    return true;
+
   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_LOCAL)
-    LOG(INFO) << "Found group type LOCAL: " << group_name;
-  else
-    LOG(INFO) << "Found group type REMOTE: " << group_name
-              << " (" << group_addr << ")";
+  ret = strcmp(group_name, kGroupName);
+  free(group_name);
 
-  // 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);
+  if (ret == 0) {
+    ret = mdg_group_info_clone(&mdgmgr->group_handle_, group);
+    if (ret != MDG_ERROR_NONE)
+      LOG(ERROR) << "Failed to clone group info: " << MDGErrorToString(ret);
+  }
 
   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;
-    }
+  mdgmgr->FindDevices();
+}
 
-    mdg_group_type_e group_type;
-    ret = mdg_group_info_get_type(group, &group_type);
-    if (ret != MDG_ERROR_NONE)
-      continue;
-    // if group is local, we don't need to join
-    if (group_type == MDG_GROUP_TYPE_LOCAL) {
-      LOG(INFO) << "Found my group. I'm the owner device";
-      return;
-    }
+void MDGManager::GroupInviteFinishCb(int result, mdg_device_h invited_device,
+    void* user_data) {
+  LOG(INFO) << "GroupInviteFinishCb called. "
+            << "result: " << result;
 
-    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_addr;
-      int ret = mdg_device_info_get_addr(device, &device_addr);
-      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_addr, 25)) {
-        owner_device = device;
-        free(device_addr);
-        break;
-      }
-      free(device_addr);
-    }
-    free(group_addr);
+  // This callback maybe called in different thread
+  std::mutex lock;
+  std::lock_guard<std::mutex> guard(lock);
 
-    if (!owner_device) {
-      LOG(ERROR) << "Cannot request invite. Cannot find proper device";
-      return;
-    }
+  mdg_device_h dev_clone;
+  int ret = mdg_device_info_clone(&dev_clone, invited_device);
+  if (ret != MDG_ERROR_NONE) {
+    LOG(ERROR) << "Failed to clone device info: " << MDGErrorToString(ret);
+    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;
-    }
+  // need to check dup?
+  MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+  mdgmgr->device_list_ = g_list_append(mdgmgr->device_list_, dev_clone);
+}
+
+bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
+  char* device_id;
+  bool is_invited;
+  char* device_addr;
+  char* model_name;
+
+  int 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_is_invited(device, &is_invited);
+  if (ret != MDG_ERROR_NONE) {
+    LOG(ERROR) << "Failed to get is_invited: " << MDGErrorToString(ret);
+    free(device_id);
+    return true;
   }
 
-  LOG(INFO) << "Group not found. Create one";
-  ret = mdg_group_create(mdgmgr->mdg_handle_, const_cast<char*>(kGroupName));
+  ret = mdg_device_info_get_addr(device, &device_addr);
+  if (ret != MDG_ERROR_NONE) {
+    LOG(ERROR) << "Failed to get device_addr: " << 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 model_name: " << MDGErrorToString(ret);
+    free(device_addr);
+    free(device_id);
+    return true;
+  }
+
+  LOG(INFO) << "Found not invited device. Invite this device. "
+            << "device_id: " << device_id
+            << ", is_invited: " << is_invited
+            << ", device_addr: " << device_addr
+            << ", model_name: " << model_name;
+
+  free(model_name);
+  free(device_addr);
+  free(device_id);
+
+  MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+  ret = mdg_group_invite_device(mdgmgr->mdg_handle_, mdgmgr->group_handle_,
+      device, const_cast<char*>(kPIN), &MDGManager::GroupInviteFinishCb,
+      user_data);
   if (ret != MDG_ERROR_NONE)
-    LOG(ERROR) << "Failed to create group: " << MDGErrorToString(ret);
+      LOG(ERROR) << "Failed to invite device: " << MDGErrorToString(ret);
+
+  return true;
 }
 
-bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
+void MDGManager::DeviceFinishCb(int result, void* user_data) {
+  LOG(INFO) << "Find device finished: " << result;
+
+  int ret;
+  MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
+  do {
+    ret = mdg_device_find(mdgmgr->mdg_handle_, kRequestTimeout, true,
+        &MDGManager::InvitedDeviceFoundCb, &MDGManager::InvitedDeviceFinishCb,
+        user_data);
+    if (ret != MDG_ERROR_IN_PROGRESS) {
+      LOG(INFO) << "Some request in progress, wait and retry in 1 second";
+      sleep(kRequestWaitingSec);
+    } else if (ret != MDG_ERROR_NONE) {
+      LOG(ERROR) << "Failed to find invited device: " << MDGErrorToString(ret);
+    }
+  } while (ret == MDG_ERROR_IN_PROGRESS);
+}
+
+bool MDGManager::InvitedDeviceFoundCb(mdg_device_h device, void* user_data) {
   char* device_id;
+  bool is_invited;
   char* device_addr;
   char* model_name;
 
@@ -234,6 +263,13 @@ bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
     return true;
   }
 
+  ret = mdg_device_info_is_invited(device, &is_invited);
+  if (ret != MDG_ERROR_NONE) {
+    LOG(ERROR) << "Failed to get is_invited: " << MDGErrorToString(ret);
+    free(device_id);
+    return true;
+  }
+
   ret = mdg_device_info_get_addr(device, &device_addr);
   if (ret != MDG_ERROR_NONE) {
     LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
@@ -249,11 +285,16 @@ bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
     return true;
   }
 
-  LOG(INFO) << "Found device. "
+  LOG(INFO) << "Found invited device. "
             << "device_id: " << device_id
+            << ", is_invited: " << is_invited
             << ", device_addr: " << device_addr
             << ", model_name: " << model_name;
 
+  // critical section: appending device list
+  std::mutex lock;
+  std::lock_guard<std::mutex> guard(lock);
+
   // need to check dup;
   MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
   mdg_device_h dev_clone = nullptr;
@@ -273,14 +314,25 @@ bool MDGManager::DeviceFoundCb(mdg_device_h device, void* user_data) {
   return true;
 }
 
-void MDGManager::DeviceFinishCb(int result, void* user_data) {
-  LOG(INFO) << "Find device finished: " << result;
+void MDGManager::InvitedDeviceFinishCb(int result, void* user_data) {
+  LOG(INFO) << "Find invited device finished: " << result;
   MDGManager* mdgmgr = static_cast<MDGManager*>(user_data);
-  mdgmgr->CreateOrJoinGroup();
+  LOG(INFO) << "Found " << g_list_length(mdgmgr->device_list_)
+            << " invited devices";
 }
 
-bool MDGManager::CreateOrJoinGroup() {
-  int ret = mdg_group_find(mdg_handle_, kRequestTimeout,
+bool MDGManager::CreateGroup() {
+  int ret = mdg_group_create(mdg_handle_, const_cast<char*>(kGroupName));
+  if (ret == MDG_ERROR_NONE) {
+    LOG(INFO) << "Group for capmgr registered";
+  } else if (ret == MDG_ERROR_ALREADY_REGISTERED) {
+    LOG(INFO) << "Group for capmgr already registered";
+  } else {
+    LOG(ERROR) << "Failed to create group: " << MDGErrorToString(ret);
+    return false;
+  }
+
+  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);
@@ -292,10 +344,12 @@ bool MDGManager::CreateOrJoinGroup() {
 
 bool MDGManager::SendData(const std::string& device_id, Command cmd,
     const unsigned char* data, size_t len) {
+  LOG(INFO) << "SendData to " << device_id;
+
   mdg_device_h device = nullptr;
   for (auto& dev : GListRange<mdg_device_h>(device_list_)) {
     char* dev_id;
-    int ret = mdg_device_info_get_device_id(device, &dev_id);
+    int ret = mdg_device_info_get_device_id(dev, &dev_id);
     if (ret != MDG_ERROR_NONE)
       continue;
     ret = strcmp(dev_id, device_id.c_str());
@@ -345,13 +399,33 @@ void MDGManager::FindDevices() {
 }
 
 void MDGManager::RegisterEndpoint() {
+  int ret = mdg_device_regist_channel(mdg_handle_,
+      const_cast<char*>(kChannelId), &MDGManager::ChannelCb, this);
+  if (ret == MDG_ERROR_NONE)
+    LOG(INFO) << "Channel for capmgr registered";
+  else if (ret == MDG_ERROR_ALREADY_REGISTERED)
+    LOG(INFO) << "Channel for capmgr already registered";
+  else
+    LOG(ERROR) << "Failed to regist channel: " << MDGErrorToString(ret);
 }
 
 void MDGManager::ExchangeCapabilities() {
   std::string caps = capmgr_->PackCapabilities();
   unsigned char* caps_data = new unsigned char[caps.size()];
-  // FIXME: pass device_id?
-  SendData({}, Command::EXCHANGE_CAPS, caps_data, caps.size());
+  memcpy(caps_data, caps.c_str(), caps.size());
+  LOG(INFO) << "Send my capabilities to "
+            << g_list_length(device_list_)
+            << " devices";
+  for (const auto& device : GListRange<mdg_device_h>(device_list_)) {
+    char* device_id;
+    int ret = mdg_device_info_get_device_id(device, &device_id);
+    if (ret != MDG_ERROR_NONE) {
+      LOG(ERROR) << "Failed to get device id: " << MDGErrorToString(ret);
+      continue;
+    }
+    SendData(device_id, Command::EXCHANGE_CAPS, caps_data, caps.size());
+    free(device_id);
+  }
   delete caps_data;
 }
 
index c0e0248e8ee31bebbb442d864403dfc8c4333c82..d04890bd2d3b5d35afeaabbd15b7340658b5585e 100644 (file)
@@ -37,21 +37,27 @@ class MDGManager : public ConnectionManager {
   };
 
   bool Initialize();
-  bool CreateOrJoinGroup();
+  bool CreateGroup();
   bool SendData(const std::string& device_id, Command cmd,
       const unsigned char* data, size_t len);
 
   static void RequestCb(char* cmd, char* device_id, unsigned char* arg,
       int len, int ret, void* user_data);
+  static void ChannelCb(int result, char* device_id, char* channel_id,
+      unsigned char* arg, int len, 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 void GroupInviteFinishCb(int result, mdg_device_h invited_device,
+      void* user_data);
   static bool DeviceFoundCb(mdg_device_h device, void* user_data);
   static void DeviceFinishCb(int result, void* user_data);
+  static bool InvitedDeviceFoundCb(mdg_device_h device, void* user_data);
+  static void InvitedDeviceFinishCb(int result, void* user_data);
 
   mdg_h mdg_handle_;
+  mdg_group_h group_handle_;
   GList* device_list_;
-  GList* group_list_;
 };
 
 }  // namespace capmgr