return (*fds)[0];
}
+int FdBroker::SendSync(const std::string& target_appid,
+ const std::string& port_name,
+ int (*fds)[2]) {
+ char sender_appid[255] = { 0, };
+ int ret;
+ if (!mock_) {
+ ret = aul_app_get_appid_bypid(getpid(), sender_appid, sizeof(sender_appid));
+ if (ret != AUL_R_OK) {
+ LOGE("Failed to get application ID. ret(%d)", ret);
+ return -1;
+ }
+ }
+
+ SocketPair main_sock_pair(mock_);
+ ret = main_sock_pair.Request(target_appid, port_name);
+ if (ret != 0)
+ return -1;
+
+ SocketPair delegate_sock_pair(mock_);
+ ret = delegate_sock_pair.Request(target_appid, port_name);
+ if (ret != 0)
+ return -1;
+
+ if (mock_) {
+ int send_fds[2];
+ send_fds[0] = main_sock_pair.Detach(SocketPair::RECEIVER);
+ send_fds[1] = delegate_sock_pair.Detach(SocketPair::RECEIVER);
+
+ ret = DBusMock::GetInst().Send("TestApp", port_name, send_fds);
+ if (ret < 0)
+ return ret;
+
+ (*fds)[0] = main_sock_pair.Detach(SocketPair::SENDER);
+ (*fds)[1] = delegate_sock_pair.Detach(SocketPair::SENDER);
+ return (*fds)[0];
+ }
+
+ FdList fd_list;
+ ret = fd_list.Add(main_sock_pair.Detach(SocketPair::RECEIVER));
+ if (ret != 0)
+ return -1;
+
+ ret = fd_list.Add(delegate_sock_pair.Detach(SocketPair::RECEIVER));
+ if (ret != 0)
+ return -1;
+
+ std::string interface_name = GetInterfaceName(target_appid, port_name);
+
+#define MAX_CNT 100
+#define MAX_SLEEP 100
+#define MIN_SLEEP 50
+#define BASE_SLEEP (1000 * 1000)
+ GDBusMessage* reply;
+ GError* err = nullptr;
+ struct timespec try_sleep_time = { 0, MIN_SLEEP * BASE_SLEEP };
+ struct timespec start_time = { 0, };
+ struct timespec end_time = { 0, };
+ int max_timeout = MAX_CNT * MAX_SLEEP;
+
+ do {
+ clock_gettime(CLOCK_MONOTONIC, &start_time);
+ GDBusMessage* msg = g_dbus_message_new_method_call(interface_name.c_str(),
+ RPC_PORT_OBJECT_PATH, interface_name.c_str(), "send_message");
+ if (msg == nullptr) {
+ LOGE("g_dbus_message_new_method_call() is failed");
+ return -1;
+ }
+
+ g_dbus_message_set_unix_fd_list(msg, fd_list.GetRaw());
+
+ reply = g_dbus_connection_send_message_with_reply_sync(
+ DBusConnectionManager::GetInst().GetConnection(),
+ msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 500, nullptr, nullptr, &err);
+ clock_gettime(CLOCK_MONOTONIC, &end_time);
+ g_object_unref(msg);
+
+ if (reply && !g_dbus_message_to_gerror(reply, &err))
+ break;
+
+ if (reply == nullptr) {
+ LOGE("g_dbus_connection_send_message_with_reply_sync() is failed");
+ if (err) {
+ LOGE("error(%s)", err->message);
+ g_error_free(err);
+ }
+ } else if (g_dbus_message_to_gerror(reply, &err)) {
+ LOGE("error(%s) was set", err->message);
+ g_error_free(err);
+ g_object_unref(reply);
+ }
+ err = nullptr;
+
+ max_timeout -= (((end_time.tv_sec - start_time.tv_sec) * 1000) +
+ ((end_time.tv_nsec - start_time.tv_nsec) / BASE_SLEEP));
+ if (max_timeout <= 0)
+ break;
+
+ nanosleep(&try_sleep_time, 0);
+ max_timeout -= (try_sleep_time.tv_nsec / BASE_SLEEP);
+ if (max_timeout <= 0)
+ break;
+
+ try_sleep_time.tv_nsec *= 2;
+ if (try_sleep_time.tv_nsec > (MAX_SLEEP * BASE_SLEEP))
+ try_sleep_time.tv_nsec = MAX_SLEEP * BASE_SLEEP;
+
+ LOGD("Retry");
+ } while (max_timeout > 0);
+
+ if (max_timeout <= 0) {
+ LOGE("Timed out");
+ return -1;
+ }
+
+ GVariant* reply_body = g_dbus_message_get_body(reply);
+ if (reply_body == nullptr) {
+ LOGE("g_dbus_message_get_body() is failed");
+ g_object_unref(reply);
+ return -1;
+ }
+
+ g_variant_get(reply_body, "(i)", &ret);
+ if (ret != 0) {
+ LOGE("Access Denied[sender_appid: %s, result: %d]", sender_appid, ret);
+ g_object_unref(reply);
+ return -EILLEGALACCESS;
+ }
+
+ LOGD("[Reply: %d]", ret);
+
+ (*fds)[0] = main_sock_pair.Detach(SocketPair::SENDER);
+ (*fds)[1] = delegate_sock_pair.Detach(SocketPair::SENDER);
+
+ return (*fds)[0];
+}
+
void FdBroker::ReceiveMessage(const char* sender_appid,
GDBusMethodInvocation* invocation) {
GDBusMessage* msg;
int FdBroker::Watch(IEventWatcher* ev, const std::string& target_appid,
const std::string& port_name) {
- int r;
-
if (ev == nullptr)
return -1;
- if (!mock_) {
- r = aul_rpc_port_prepare_stub(target_appid.c_str(), port_name.c_str());
- if (r != AUL_R_OK) {
- LOGE("Failed to prepare stub %s:%s [ret : %d]",
- target_appid.c_str(), port_name.c_str(), r);
- return r;
- }
- }
+ int ret = Prepare(target_appid, port_name);
+ if (ret < 0)
+ return ret;
watcher_ = ev;
watch_appid_ = target_appid;
watch_port_name_ = port_name;
if (mock_) {
- r = DBusMock::GetInst().Watch(ev, target_appid, port_name);
- if (r < 0)
+ ret = DBusMock::GetInst().Watch(ev, target_appid, port_name);
+ if (ret < 0)
return -1;
return 0;
return 0;
}
+int FdBroker::Prepare(const std::string& target_appid,
+ const std::string& port_name) {
+ if (!mock_) {
+ int ret = aul_rpc_port_prepare_stub(target_appid.c_str(),
+ port_name.c_str());
+ if (ret != AUL_R_OK) {
+ LOGE("Failed to prepare stub %s:%s [ret : %d]",
+ target_appid.c_str(), port_name.c_str(), ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
void FdBroker::OnResultReceived(GObject* source_object,
GAsyncResult* res,
gpointer user_data) {
return RPC_PORT_ERROR_NONE;
}
+int Proxy::ConnectSync(std::string appid, std::string port_name,
+ IEventListener* ev) {
+ if (ev == nullptr)
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+ if (listener_ != nullptr) {
+ LOGW("Already connected");
+ return RPC_PORT_ERROR_INVALID_PARAMETER;
+ }
+
+ listener_ = ev;
+ target_appid_ = std::move(appid);
+ port_name_ = std::move(port_name);
+
+ int ret = fd_broker_.Prepare(target_appid_, port_name_);
+ if (ret < 0) {
+ listener_ = nullptr;
+ if (ret == -EILLEGALACCESS)
+ return RPC_PORT_ERROR_PERMISSION_DENIED;
+
+ return RPC_PORT_ERROR_IO_ERROR;
+ }
+
+ fds_[0] = 0;
+ fds_[1] = 0;
+ ret = fd_broker_.SendSync(target_appid_, port_name_, &fds_);
+ if (ret <= 0) {
+ listener_ = nullptr;
+ if (ret == -EILLEGALACCESS)
+ return RPC_PORT_ERROR_PERMISSION_DENIED;
+
+ return RPC_PORT_ERROR_IO_ERROR;
+ }
+
+ main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
+ delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
+ listener_->OnConnected(target_appid_, main_port_.get());
+
+ return RPC_PORT_ERROR_NONE;
+}
+
gboolean Proxy::DbusNameTimeout(gpointer user_data) {
Proxy* obj = static_cast<Proxy*>(user_data);