Remove circular dependency 34/279934/1
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 19 Aug 2022 07:16:34 +0000 (07:16 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 19 Aug 2022 07:16:34 +0000 (07:16 +0000)
tidl package has a dependency of rpc-port. Currently, there is a
circular dedenecy problem. This patch solves it.

Change-Id: If60079ad21220fece3624d34f3cb9487fd17c006
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
benchmark/server/BenchmarkStub.cc [new file with mode: 0644]
benchmark/server/BenchmarkStub.h [new file with mode: 0644]
benchmark/tool/BenchmarkProxy.cc [new file with mode: 0644]
benchmark/tool/BenchmarkProxy.h [new file with mode: 0644]
packaging/rpc-port.spec

diff --git a/benchmark/server/BenchmarkStub.cc b/benchmark/server/BenchmarkStub.cc
new file mode 100644 (file)
index 0000000..45d16c8
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Generated by tidlc 1.9.1.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <libgen.h>
+#include <dlog.h>
+
+#include "BenchmarkStub.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_STUB"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "1.9.1"
+#endif
+
+namespace rpc_port {
+namespace BenchmarkStub {
+
+namespace stub {
+
+Benchmark::ServiceBase::ServiceBase(std::string sender, std::string instance)
+    : sender_(std::move(sender)), instance_(std::move(instance)),
+      active_object_(new ActiveObject()) {}
+
+void Benchmark::ServiceBase::SetPort(rpc_port_h port) {
+  port_ = port;
+}
+
+void Benchmark::ServiceBase::Disconnect() {
+  int ret = rpc_port_disconnect(port_);
+  if (ret == RPC_PORT_ERROR_NONE) {
+    _E("Failed to disconnect the port(%d)", ret);
+    return;
+  }
+
+  port_ = nullptr;
+}
+
+
+std::atomic<int> Benchmark::CallbackBase::seq_num_ { 0 };
+
+Benchmark::CallbackBase::CallbackBase(int delegate_id, bool once)
+    : id_(delegate_id), once_(once) {
+  seq_id_ = seq_num_++;
+}
+
+int Benchmark::CallbackBase::GetId() const {
+  return id_;
+}
+
+int Benchmark::CallbackBase::GetSeqId() const {
+  return seq_id_;
+}
+
+bool Benchmark::CallbackBase::IsOnce() const {
+  return once_;
+}
+
+std::string Benchmark::CallbackBase::GetTag() const {
+  return std::to_string(id_) + "::" + std::to_string(seq_id_);
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const Benchmark::CallbackBase& cb) {
+  rpc_port_parcel_write_int32(h, cb.id_);
+  rpc_port_parcel_write_int32(h, cb.seq_id_);
+  rpc_port_parcel_write_bool(h, cb.once_);
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, Benchmark::CallbackBase& cb) {
+  rpc_port_parcel_read_int32(h, &cb.id_);
+  rpc_port_parcel_read_int32(h, &cb.seq_id_);
+  rpc_port_parcel_read_bool(h, &cb.once_);
+
+  return h;
+}
+
+Benchmark::Benchmark() {
+  int r = rpc_port_stub_create(&stub_, "Benchmark");
+  if (r != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create stub handle");
+    throw InvalidIOException();
+  }
+  rpc_port_stub_add_connected_event_cb(stub_, OnConnectedCB, this);
+  rpc_port_stub_add_disconnected_event_cb(stub_, OnDisconnectedCB, this);
+  rpc_port_stub_add_received_event_cb(stub_, OnReceivedCB, this);
+}
+
+Benchmark::~Benchmark() {
+  for (auto& i : services_) {
+    i->OnTerminate();
+  }
+
+  if (stub_) {
+    rpc_port_stub_destroy(stub_);
+  }
+}
+
+void Benchmark::Listen(std::shared_ptr<Benchmark::ServiceBase::Factory> service_factory) {
+  service_factory_ = std::move(service_factory);
+  int r = rpc_port_stub_listen(stub_);
+  if (r != RPC_PORT_ERROR_NONE) {
+    _E("Failed to listen stub");
+    switch (r) {
+      case RPC_PORT_ERROR_INVALID_PARAMETER:
+      case RPC_PORT_ERROR_IO_ERROR:
+        throw InvalidIOException();
+    }
+  }
+}
+
+void Benchmark::OnConnectedCB(const char* sender, const char* instance, void* data) {
+  Benchmark* stub = static_cast<Benchmark*>(data);
+  auto s = stub->service_factory_->CreateService(sender, instance);
+
+  rpc_port_h port;
+  int ret = rpc_port_stub_get_port(stub->stub_, RPC_PORT_PORT_CALLBACK, instance, &port);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to get the port(%d)", ret);
+    return;
+  }
+
+  s->SetPort(port);
+  s->OnCreate();
+  stub->services_.emplace_back(std::move(s));
+}
+
+void Benchmark::OnDisconnectedCB(const char* sender, const char* instance, void *data) {
+  Benchmark* stub = static_cast<Benchmark*>(data);
+
+  for (auto& i : stub->services_) {
+    if (i->GetInstance() == instance) {
+      i->OnTerminate();
+      stub->services_.remove(i);
+      return;
+    }
+  }
+}
+
+int Benchmark::OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void *data)
+{
+  auto* cxt = static_cast<Benchmark*>(data);
+  rpc_port_parcel_h p;
+  rpc_port_parcel_h result;
+  rpc_port_parcel_h header;
+  int seq_num = -1;
+  int cmd;
+  int ret;
+  std::shared_ptr<ServiceBase> b;
+  rpc_port_h callback_port;
+
+  for (auto& i : cxt->services_) {
+    if (i->GetInstance() == instance) {
+      b = i;
+      break;
+    }
+  }
+
+  if (b.get() == nullptr) {
+    _E("Failed to find Benchmark context(%s)", instance);
+    return -1;
+  }
+
+  ret = rpc_port_stub_get_port(cxt->stub_, RPC_PORT_PORT_CALLBACK, instance,
+      &callback_port);
+  if (ret != 0) {
+    _E("Failed to get callback port");
+  }
+
+  ret = rpc_port_parcel_create_from_port(&p, port);
+  if (ret != 0) {
+    _E("Failed to create parcel from port");
+    return ret;
+  }
+
+  rpc_port_parcel_get_header(p, &header);
+  rpc_port_parcel_header_get_seq_num(header, &seq_num);
+  _W("[Sequence] %d", seq_num);
+
+  rpc_port_parcel_create(&result);
+  rpc_port_parcel_get_header(result, &header);
+  rpc_port_parcel_header_set_tag(header, TIDL_VERSION);
+  rpc_port_parcel_header_set_seq_num(header, seq_num);
+
+  rpc_port_parcel_read_int32(p, &cmd);
+
+  switch (cmd) {
+    case static_cast<int>(MethodId::Test): {
+      char* param1_raw  = nullptr;
+      rpc_port_parcel_read_string(p, &param1_raw);
+      std::string param1(param1_raw);
+      free(param1_raw);
+      auto retVal = b->Test(param1);
+      rpc_port_parcel_write_int32(result, static_cast<int>(MethodId::__Result));
+      rpc_port_parcel_write_int32(result, retVal);
+      ret = rpc_port_parcel_send(result, port);
+      _I("Parcel send result(%d)", ret);
+      break;
+    }
+
+    default:
+      _E("Unknown command(%d)", cmd);
+      rpc_port_parcel_destroy(p);
+      rpc_port_parcel_destroy(result);
+      return -1;
+  }
+
+  rpc_port_parcel_destroy(p);
+  rpc_port_parcel_destroy(result);
+
+  return ret;
+}
+
+}  // namespace stub
+}  // namespace BenchmarkStub
+}  // namespace rpc_port
diff --git a/benchmark/server/BenchmarkStub.h b/benchmark/server/BenchmarkStub.h
new file mode 100644 (file)
index 0000000..8c72233
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Generated by tidlc 1.9.1.
+ */
+
+#pragma once
+
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+#include <rpc-port.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <list>
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <deque>
+#include <thread>
+
+namespace rpc_port {
+namespace BenchmarkStub {
+
+class Bundle final {
+ public:
+  Bundle() {
+    raw_ = bundle_create();
+  }
+
+  Bundle(bundle* b) {
+    raw_ = b;
+  }
+
+  ~Bundle() {
+    if (raw_)
+      bundle_free(raw_);
+  }
+
+  Bundle(Bundle&& b) : raw_(b.raw_) {
+    b.raw_ = nullptr;
+  }
+
+  Bundle& operator = (Bundle&& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = b.raw_;
+      b.raw_ = nullptr;
+    }
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = bundle_dup(b.GetHandle());
+    }
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+class File final {
+ public:
+  File() {
+  }
+
+  File(std::string filename) {
+    filename_ = filename;
+  }
+
+  std::string GetFileName() const {
+    return filename_;
+  }
+
+ private:
+  std::string filename_;
+};
+
+namespace stub {
+
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class InvalidCallbackException : public Exception {};
+class Job {
+ public:
+  class IEvent {
+   public:
+    virtual ~IEvent() = default;
+    virtual void Run() = 0;
+  };
+
+  Job() : handler_(nullptr) {
+  }
+
+  Job(IEvent* handler) : handler_(handler) {
+  }
+  virtual ~Job() = default;
+
+  Job(const Job& job) {
+    handler_ = job.handler_;
+  }
+
+  Job& operator = (const Job& job) {
+    if (this != &job)
+      handler_ = job.handler_;
+    return *this;
+  }
+  Job(Job&& job) noexcept {
+    handler_ = job.handler_;
+    job.handler_ = nullptr;
+  }
+
+  Job& operator = (Job&& job) noexcept {
+    if (this != &job) {
+      handler_ = job.handler_;
+      job.handler_ = nullptr;
+    }
+    return *this;
+  }
+
+  void Invoke() {
+    if (handler_)
+      handler_->Run();
+  }
+
+ private:
+  IEvent* handler_;
+};
+
+
+template <class T>
+class SharedQueue {
+ public:
+  SharedQueue() = default;
+  virtual ~SharedQueue() = default;
+
+  void Push(T item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    queue_.push_back(item);
+    cond_var_.notify_one();
+  }
+
+  void PushFront(T item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    queue_.push_front(item);
+    cond_var_.notify_one();
+  }
+
+  bool TryAndPop(T& item) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    if (queue_.empty())
+       return false;
+
+    item = queue_.front();
+    queue_.pop_front();
+
+    return true;
+  }
+
+  void WaitAndPop(T& item) {
+    std::unique_lock<std::mutex> lock(mutex_);
+    while (queue_.empty())
+      cond_var_.wait(lock);
+
+    item = queue_.front();
+    queue_.pop_front();
+  }
+
+  bool Empty() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return queue_.empty();
+  }
+
+  int Size() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return queue_.size();
+  }
+
+ private:
+  std::deque<T> queue_;
+  mutable std::mutex mutex_;
+  std::condition_variable cond_var_;
+};
+
+class ActiveObject : public Job::IEvent {
+ public:
+  ActiveObject() {
+    thread_ = std::thread([&]{
+          do {
+            std::shared_ptr<Job> item;
+            queue_.WaitAndPop(item);
+            item->Invoke();
+          } while (!done_);
+        });
+  }
+  virtual ~ActiveObject() {
+    Quit();
+    thread_.join();
+  }
+
+ public:
+  void Send(std::shared_ptr<Job> job) {
+    queue_.Push(std::move(job));
+  }
+
+ private:
+  void Quit() {
+    Send(std::shared_ptr<Job>(new (std::nothrow) Job(this)));
+  }
+  void Run() override {
+    done_ = true;
+  }
+
+ private:
+  std::thread thread_;
+  bool done_ = false;
+  SharedQueue<std::shared_ptr<Job>> queue_;
+};
+
+
+class Benchmark final {
+ public:
+  class ServiceBase;
+
+  class CallbackBase {
+   public:
+    CallbackBase(int delegate_id, bool once);
+    virtual ~CallbackBase() = default;
+
+    int GetId() const;
+    int GetSeqId() const;
+    bool IsOnce() const;
+    std::string GetTag() const;
+
+   private:
+    friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);
+    friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);
+
+    static std::atomic<int> seq_num_;
+    int id_;
+    int seq_id_;
+    bool once_;
+  };
+
+  class ServiceBase {
+   public:
+    class Factory {
+     public:
+      virtual ~Factory() = default;
+
+      /// <summary>
+      /// The method for making service instances
+      /// </summary>
+      /// <param name="sender">The client app ID</param>
+      /// <param name="instance">The client instance ID</param>
+      virtual std::unique_ptr<ServiceBase> CreateService(std::string sender, std::string instance) = 0;
+    };
+
+    virtual ~ServiceBase() = default;
+
+    /// <summary>
+    /// Gets client app ID
+    /// </summary>
+    const std::string& GetSender() const {
+      return sender_;
+    }
+
+    /// <summary>
+    /// Gets client instance ID
+    /// </summary>
+    const std::string& GetInstance() const {
+      return instance_;
+    }
+
+    /// <summary>
+    /// Sets the client app port
+    /// </summary>
+    /// <param name="port">The port of the client</param>
+    void SetPort(rpc_port_h port);
+
+    /// <summary>
+    /// Disconnects from the client app
+    /// </summary>
+    /// <exception cref="InvalidIOException">
+    /// Thrown when internal I/O error happen.
+    /// </exception>
+    void Disconnect();
+
+    /// <summary>
+    /// This method will be called when the client is connected
+    /// </summary>
+    virtual void OnCreate() = 0;
+
+    /// <summary>
+    /// This method will be called when the client is disconnected
+    /// </summary>
+    virtual void OnTerminate() = 0;
+
+    void Dispatch(rpc_port_h port, rpc_port_h callback_port,
+        rpc_port_parcel_h parcel, std::shared_ptr<ServiceBase> service);
+
+    virtual int Test(std::string data) = 0;
+
+   protected:
+    ServiceBase(std::string sender, std::string instance);
+
+   private:
+    std::string sender_;
+    std::string instance_;
+    rpc_port_h port_ = nullptr;
+    std::unique_ptr<ActiveObject> active_object_;
+  };
+
+  Benchmark();
+  ~Benchmark();
+
+  /// <summary>
+  /// Listens to client apps
+  /// </summary>
+  /// <param name="service_factory">The factory object for making service instances</param>
+  /// <exception cref="InvalidIOException">
+  /// Thrown when internal I/O error happen.
+  /// </exception>
+  void Listen(std::shared_ptr<ServiceBase::Factory> service_factory);
+
+  /// <summary>
+  /// Gets service objects which are connected
+  /// </summary>
+  /// <returns>The list of service objects which are connected</returns>
+  const std::list<std::shared_ptr<ServiceBase>>& GetServices() const {
+    return services_;
+  }
+
+ private:
+  enum class MethodId : int {
+    __Result = 0,
+    __Callback = 1,
+    Test = 2,
+
+  };
+
+  enum class DelegateId : int {
+
+  };
+  static void OnConnectedCB(const char* sender, const char* instance, void* data);
+  static void OnDisconnectedCB(const char* sender, const char* instance, void* data);
+  static int OnReceivedCB(const char* sender, const char* instance, rpc_port_h port, void* data);
+
+  rpc_port_stub_h stub_ = nullptr;
+  std::shared_ptr<ServiceBase::Factory> service_factory_;
+  std::list<std::shared_ptr<ServiceBase>> services_;
+};
+}  // namespace stub
+}  // namespace BenchmarkStub
+}  // namespace rpc_port
diff --git a/benchmark/tool/BenchmarkProxy.cc b/benchmark/tool/BenchmarkProxy.cc
new file mode 100644 (file)
index 0000000..df7b61b
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Generated by tidlc 1.9.1.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <dlog.h>
+
+#include "BenchmarkProxy.h"
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RPC_PORT_PROXY"
+
+#ifdef _E
+#undef _E
+#endif
+
+#ifdef _W
+#undef _W
+#endif
+
+#ifdef _I
+#undef _I
+#endif
+
+#ifdef _D
+#undef _D
+#endif
+
+#define _E(fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _W(fmt, ...) dlog_print(DLOG_WARN, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _I(fmt, ...) dlog_print(DLOG_INFO, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define _D(fmt, ...) dlog_print(DLOG_DEBUG, LOG_TAG, "%s: %s(%d) > " fmt, basename(const_cast<char*>(__FILE__)), __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifndef TIDL_VERSION
+#define TIDL_VERSION "1.9.1"
+#endif
+
+namespace rpc_port {
+namespace BenchmarkProxy {
+
+namespace proxy {
+
+
+std::atomic<int> Benchmark::CallbackBase::seq_num_ { 0 };
+
+Benchmark::CallbackBase::CallbackBase(int delegate_id, bool once)
+    : id_(delegate_id), once_(once) {
+  seq_id_ = seq_num_++;
+}
+
+int Benchmark::CallbackBase::GetId() const {
+  return id_;
+}
+
+int Benchmark::CallbackBase::GetSeqId() const {
+  return seq_id_;
+}
+
+bool Benchmark::CallbackBase::IsOnce() const {
+  return once_;
+}
+
+std::string Benchmark::CallbackBase::GetTag() const {
+  return std::to_string(id_) + "::" + std::to_string(seq_id_);
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const Benchmark::CallbackBase& cb) {
+  rpc_port_parcel_write_int32(h, cb.id_);
+  rpc_port_parcel_write_int32(h, cb.seq_id_);
+  rpc_port_parcel_write_bool(h, cb.once_);
+
+  return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, Benchmark::CallbackBase& cb) {
+  rpc_port_parcel_read_int32(h, &cb.id_);
+  rpc_port_parcel_read_int32(h, &cb.seq_id_);
+  rpc_port_parcel_read_bool(h, &cb.once_);
+
+  return h;
+}
+
+Benchmark::Benchmark(IEventListener* listener, const std::string& target_appid)
+    : port_(nullptr), callback_port_(nullptr), proxy_(nullptr),
+      listener_(listener), target_appid_(target_appid) {
+  int r = rpc_port_proxy_create(&proxy_);
+
+  if (r != RPC_PORT_ERROR_NONE) {
+    _E("Failed to create proxy");
+    throw InvalidIOException();
+  }
+
+  rpc_port_proxy_add_connected_event_cb(proxy_, OnConnectedCB, this);
+  rpc_port_proxy_add_disconnected_event_cb(proxy_, OnDisconnectedCB, this);
+  rpc_port_proxy_add_rejected_event_cb(proxy_, OnRejectedCB, this);
+  rpc_port_proxy_add_received_event_cb(proxy_, OnReceivedCB, this);
+}
+
+Benchmark::~Benchmark() {
+  if (proxy_)
+    rpc_port_proxy_destroy(proxy_);
+}
+
+void Benchmark::Connect(bool sync) {
+  int ret;
+  if (sync)
+    ret = rpc_port_proxy_connect_sync(proxy_, target_appid_.c_str(), "Benchmark");
+  else
+    ret = rpc_port_proxy_connect(proxy_, target_appid_.c_str(), "Benchmark");
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to connect Benchmark");
+    switch (ret) {
+      case RPC_PORT_ERROR_INVALID_PARAMETER:
+        throw InvalidIDException();
+
+      case RPC_PORT_ERROR_IO_ERROR:
+        throw InvalidIOException();
+
+      case RPC_PORT_ERROR_PERMISSION_DENIED:
+        throw PermissionDeniedException();
+    }
+  }
+}
+
+void Benchmark::Disconnect() {
+  int ret = rpc_port_disconnect(port_);
+  if (ret != RPC_PORT_ERROR_NONE) {
+    _E("Failed to disconnect Benchmark");
+    throw InvalidIDException();
+  }
+}
+
+void Benchmark::DisposeCallback(const std::string& tag) {
+  for (auto& i : delegate_list_) {
+    if (i->GetTag() == tag) {
+      delegate_list_.remove(i);
+      return;
+    }
+  }
+}
+
+void Benchmark::ProcessReceivedEvent(rpc_port_parcel_h parcel) {
+  int id = 0;
+  int seq_id = 0;
+  bool once = false;
+
+  rpc_port_parcel_read_int32(parcel, &id);
+  rpc_port_parcel_read_int32(parcel, &seq_id);
+  rpc_port_parcel_read_bool(parcel, &once);
+
+  for (auto& i : delegate_list_) {
+    if (i->GetId() == id && i->GetSeqId() == seq_id) {
+      i->OnReceivedEvent(parcel);
+      if (i->IsOnce())
+        delegate_list_.remove(i);
+      break;
+    }
+  }
+}
+
+void Benchmark::ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port) {
+  do {
+    rpc_port_parcel_h p;
+    int ret = rpc_port_parcel_create_from_port(&p, port);
+    int cmd;
+
+    if (ret != 0)
+      break;
+    rpc_port_parcel_read_int32(p, &cmd);
+    if (cmd == static_cast<int>(MethodId::__Result)) {
+      *parcel = p;
+      return;
+    }
+
+    rpc_port_parcel_destroy(p);
+    *parcel = nullptr;
+  } while (true);
+  *parcel = nullptr;
+}
+
+void Benchmark::OnConnectedCB(const char *ep, const char *port_name, rpc_port_h port, void *data) {
+  Benchmark* l = static_cast<Benchmark*>(data);
+  rpc_port_h cb_port;
+
+  l->port_ = port;
+  rpc_port_proxy_get_port(l->proxy_, RPC_PORT_PORT_CALLBACK, &cb_port);
+  l->callback_port_ = cb_port;
+  l->listener_->OnConnected();
+}
+
+void Benchmark::OnDisconnectedCB(const char *ep, const char *port_name, void *data) {
+  Benchmark* l = static_cast<Benchmark*>(data);
+  l->delegate_list_.clear();
+  l->listener_->OnDisconnected();
+}
+
+void Benchmark::OnRejectedCB(const char *ep, const char *port_name, void *data) {
+  Benchmark* l = static_cast<Benchmark*>(data);
+  l->listener_->OnRejected();
+}
+
+void Benchmark::OnReceivedCB(const char *ep, const char *port_name, void *data) {
+  Benchmark* l = static_cast<Benchmark*>(data);
+  int cmd;
+  rpc_port_parcel_h parcel_received;
+
+  if (rpc_port_parcel_create_from_port(&parcel_received, l->callback_port_) != 0) {
+    _E("Failed to create parcel from port");
+    return;
+  }
+
+  rpc_port_parcel_read_int32(parcel_received, &cmd);
+  if (cmd != static_cast<int>(MethodId::__Callback)) {
+    rpc_port_parcel_destroy(parcel_received);
+    return;
+  }
+
+  l->ProcessReceivedEvent(parcel_received);
+  rpc_port_parcel_destroy(parcel_received);
+}
+
+
+int Benchmark::Test(std::string data) {
+  if (port_ == nullptr) {
+    _E("Not connected");
+    throw NotConnectedSocketException();
+  }
+
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::Test));
+  rpc_port_parcel_write_string(p, data.c_str());
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+
+  // Send
+  int r = rpc_port_parcel_send(p, port_);
+  if (r != RPC_PORT_ERROR_NONE) {
+    _E("Failed to send parcel. result(%d)", r);
+    rpc_port_parcel_destroy(p);
+    throw InvalidIOException();
+  }
+
+  int ret;
+  bool done_ = false;
+  do {
+    rpc_port_parcel_h parcel_received = nullptr;
+    // Receive
+    ConsumeCommand(&parcel_received, port_);
+    if (parcel_received == nullptr) {
+      _E("Invalid protocol");
+      throw InvalidProtocolException();
+    }
+
+    rpc_port_parcel_get_header(parcel_received, &header_);
+    char* tag_ = nullptr;
+    rpc_port_parcel_header_get_tag(header_, &tag_);
+    std::unique_ptr<char, decltype(std::free)*> tag_auto_(tag_, std::free);
+    if (tag_ && tag_[0] != '\0') {
+      _W("[Version] %s", tag_);
+      int seq_num_received_ = -1;
+      rpc_port_parcel_header_get_seq_num(header_, &seq_num_received_);
+      if (seq_num_received_ != seq_num_) {
+        _E("Invalid protocol. %d", seq_num_received_);
+        rpc_port_parcel_destroy(parcel_received);
+        continue;
+      }
+    }
+    done_ = true;
+
+    rpc_port_parcel_read_int32(parcel_received, &ret);
+
+    rpc_port_parcel_destroy(parcel_received);
+  } while (!done_);
+
+  rpc_port_parcel_destroy(p);
+
+  return ret;
+
+}
+}  // namespace proxy
+}  // namespace BenchmarkProxy
+}  // namespace rpc_port
diff --git a/benchmark/tool/BenchmarkProxy.h b/benchmark/tool/BenchmarkProxy.h
new file mode 100644 (file)
index 0000000..43edad5
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Generated by tidlc 1.9.1.
+ */
+
+#pragma once
+
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+#include <rpc-port.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <mutex>
+#include <list>
+#include <atomic>
+
+namespace rpc_port {
+namespace BenchmarkProxy {
+class Bundle final {
+ public:
+  Bundle() {
+    raw_ = bundle_create();
+  }
+
+  Bundle(bundle* b) {
+    raw_ = b;
+  }
+
+  ~Bundle() {
+    if (raw_)
+      bundle_free(raw_);
+  }
+
+  Bundle(Bundle&& b) : raw_(b.raw_) {
+    b.raw_ = nullptr;
+  }
+
+  Bundle& operator = (Bundle&& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = b.raw_;
+      b.raw_ = nullptr;
+    }
+    return *this;
+  }
+
+  Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+  Bundle& operator = (const Bundle& b) {
+    if (this != &b) {
+      if (raw_)
+        bundle_free(raw_);
+
+      raw_ = bundle_dup(b.GetHandle());
+    }
+    return *this;
+  }
+
+  bundle* GetHandle() const {
+    return raw_;
+  }
+
+ private:
+  bundle* raw_;
+};
+
+class File final {
+ public:
+  File() {
+  }
+
+  File(std::string filename) {
+    filename_ = filename;
+  }
+
+  std::string GetFileName() const {
+    return filename_;
+  }
+
+ private:
+  std::string filename_;
+};
+
+
+namespace proxy {
+
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class PermissionDeniedException : public Exception {};
+class InvalidIDException : public Exception {};
+
+class Benchmark {
+ public:
+
+  class CallbackBase {
+   public:
+    CallbackBase(int delegate_id, bool once);
+    virtual ~CallbackBase() = default;
+    virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;
+    int GetId() const;
+    int GetSeqId() const;
+    bool IsOnce() const;
+    std::string GetTag() const;
+
+   private:
+    friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);
+    friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);
+
+    static std::atomic<int> seq_num_;
+    int id_;
+    int seq_id_;
+    bool once_;
+  };
+
+  class IEventListener {
+   public:
+    /// <summary>
+    /// This method will be invoked when the client app is connected to the servicece app.
+    /// </summary>
+    virtual void OnConnected() = 0;
+
+    /// <summary>
+    /// This method will be invoked after the client app was disconnected from the servicece app.
+    /// </summary>
+    virtual void OnDisconnected() = 0;
+
+    /// <summary>
+    /// This method will be invoked when the service app rejects the client app.
+    /// </summary>
+    virtual void OnRejected() = 0;
+  };
+
+  /// <summary>
+  /// Constructor for this class
+  /// </summary>
+  /// <param name="listener">The listener for events</param>
+  /// <param name="target_appid">The service app ID to connect</param>
+  Benchmark(IEventListener* listener, const std::string& target_appid);
+
+  /// <summary>
+  /// Destructor for this class
+  /// </summary>
+  virtual ~Benchmark();
+
+  /// <summary>
+  /// Connects to the service app.
+  /// </summary>
+  /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+  /// <privilege>http://tizen.org/privilege/datasharing</privilege>
+  //  <param name="sync">if true, connects to the service app synchornously</param>
+  /// <exception cref="InvalidIDException">
+  /// Thrown when the appid to connect is invalid.
+  /// </exception>
+  /// <exception cref="InvalidIOException">
+  /// Thrown when internal I/O error happen.
+  /// </exception>
+  /// <exception cref="PermissionDeniedException">
+  /// Thrown when the permission is denied.
+  /// </exception>
+  /// <remark> If you want to use this method, you must add privileges.</remark>
+  void Connect(bool sync = false);
+
+  /// <summary>
+  /// Disconnects from the service app.
+  /// </summary>
+  /// <exception cref="InvalidIDException">
+  /// Thrown when the stub port is invalid.
+  /// </exception>
+  void Disconnect();
+
+  /// <summary>
+  /// Disposes delegate objects in this interface
+  /// </summary>
+  /// <param name="tag">The tag string from delegate object</param>
+  void DisposeCallback(const std::string& tag);
+
+  int Test(std::string data);
+
+ private:
+  enum class MethodId : int {
+    __Result = 0,
+    __Callback = 1,
+    Test = 2,
+
+  };
+
+  enum class DelegateId : int {
+
+  };
+  void ProcessReceivedEvent(rpc_port_parcel_h parcel);
+  void ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port);
+
+  static void OnConnectedCB(const char *ep, const char *port_name,
+                            rpc_port_h port, void *data);
+  static void OnDisconnectedCB(const char *ep, const char *port_name,
+                               void *data);
+  static void OnRejectedCB(const char *ep, const char *port_name, void *data);
+  static void OnReceivedCB(const char *ep, const char *port_name, void *data);
+
+  rpc_port_h port_;
+  rpc_port_h callback_port_;
+  rpc_port_proxy_h proxy_;
+  IEventListener* listener_;
+  std::recursive_mutex mutex_;
+  std::list<std::unique_ptr<CallbackBase>> delegate_list_;
+  std::string target_appid_;
+};
+}  // namespace proxy
+}  // namespace BenchmarkProxy
+}  // namespace rpc_port
index c63eb21..b810b1e 100644 (file)
@@ -19,7 +19,6 @@ BuildRequires:  pkgconfig(parcel)
 BuildRequires:  pkgconfig(pkgmgr)
 BuildRequires:  pkgconfig(pkgmgr-info)
 BuildRequires:  pkgconfig(uuid)
-BuildRequires:  tidl
 
 %if 0%{?gcov:1}
 BuildRequires:  lcov
@@ -70,11 +69,6 @@ RPC Port gcov objects
 %setup -q
 cp %{SOURCE1001} .
 
-tidlc -p -l C++ -i ./benchmark/tidl/test.tidl -o BenchmarkProxy
-mv ./BenchmarkProxy.* ./benchmark/tool/
-tidlc -s -l C++ -i ./benchmark/tidl/test.tidl -o BenchmarkStub
-mv ./BenchmarkStub.* ./benchmark/server/
-
 %build
 %if 0%{?gcov:1}
 export CFLAGS+=" -fprofile-arcs -ftest-coverage"