Add the header handle of the parcel 03/258603/13
authorHwankyu Jhun <h.jhun@samsung.com>
Fri, 21 May 2021 04:06:27 +0000 (13:06 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Fri, 13 Aug 2021 02:09:46 +0000 (02:09 +0000)
Adds:
 - rpc_port_parcel_get_header()
 - rpc_port_parcel_header_set_seq_num()
 - rpc_port_parcel_header_get_seq_num()
 - rpc_port_parcel_header_get_timestamp()

Change-Id: I4049532b2c6a92e657861dbfc1dbe66a895081d1
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
include/rpc-port-internal.h
include/rpc-port-parcel.h
src/parcel-header-internal.cc [new file with mode: 0644]
src/parcel-header-internal.hh [new file with mode: 0644]
src/parcel-internal.cc [new file with mode: 0644]
src/parcel-internal.hh [new file with mode: 0644]
src/rpc-port-parcel.cc
test/unit_tests/rpc_port_parcel_test.cc

index ab99261..999f73f 100644 (file)
@@ -51,7 +51,7 @@ uid_t rpc_port_get_target_uid(void);
  * @param[in]   extra           The extra data
  * @return @c 0 on success,
  *         otherwise a negative error value
- * @see rpc_port_register_proc_info()
+ * @see rpc_port_deregister_proc_info()
  */
 int rpc_port_register_proc_info(const char *proc_name, bundle *extra);
 
@@ -60,7 +60,7 @@ int rpc_port_register_proc_info(const char *proc_name, bundle *extra);
  * @since_tizen 6.5
  * @return @c 0 on success,
  *         otherwise a negative error value
- * @see rpc_port_deregister_proc_info()
+ * @see rpc_port_register_proc_info()
  */
 int rpc_port_deregister_proc_info(void);
 
index 3b39802..292dfd6 100644 (file)
@@ -18,6 +18,8 @@
 #define __TIZEN_APPFW_RPC_PORT_PARCEL_INCLUDE_H__
 
 #include <stdbool.h>
+#include <sys/time.h>
+
 #include <bundle.h>
 #include <rpc-port.h>
 
@@ -37,12 +39,18 @@ extern "C" {
 typedef void *rpc_port_parcel_h;
 
 /**
+ * @brief The header handle of the rpc port parcel.
+ * @since_tizen 6.5
+ */
+typedef void *rpc_port_parcel_header_h;
+
+/**
  * @brief The interface for converting data to/from a parcel.
  * @since_tizen @if MOBILE 4.0 @elseif WEARABLE 5.0 @endif
  */
 typedef struct __rpc_port_parcelable {
-       void (*to)(rpc_port_parcel_h h, void *data);
-       void (*from)(rpc_port_parcel_h h, void *data);
+       void (*to)(rpc_port_parcel_h h, void *data);  /**< The function pointer to read from parcel */
+       void (*from)(rpc_port_parcel_h h, void *data);  /**< The function pointer to write to parcel */
 } rpc_port_parcelable_t;
 
 /**
@@ -424,6 +432,59 @@ int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf, unsigned
 int rpc_port_parcel_burst_write(rpc_port_parcel_h h, const unsigned char *buf, unsigned int size);
 
 /**
+ * @brief Gets the header handle of the rpc port parcel.
+ * @since_tizen 6.5
+ * @remarks The @a header is managed by the platform and will be released when rpc_port_parcel_destroy() is called.
+ * @param[in] h The rpc port parcel handle
+ * @param[out] header The header handle of the rpc port parcel
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int rpc_port_parcel_get_header(rpc_port_parcel_h h, rpc_port_parcel_header_h *header);
+
+/**
+ * @brief Sets the sequence number to the header handle of the rpc port parcel.
+ * @since_tizen 6.5
+ * @param[in] header The header handler of the rpc port parcel
+ * @param[in] seq_num The sequence number
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see rpc_port_parcel_header_get_seq_num()
+ */
+int rpc_port_parcel_header_set_seq_num(rpc_port_parcel_header_h header, int seq_num);
+
+/**
+ * @brief Gets the sequence number from the header handle of the rpc port parcel.
+ * @since_tizen 6.5
+ * @param[in] header The header handle of the rpc port parcel
+ * @param[out] seq_num The sequence number
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see rpc_port_parcel_header_set_seq_num()
+ */
+int rpc_port_parcel_header_get_seq_num(rpc_port_parcel_header_h header, int *seq_num);
+
+/**
+ * @brief Gets the timestamp from the header handle of the rpc port parcel.
+ * @since_tizen 6.5
+ * @remarks The @a timestamp represents monotonic time since some unspecified starting point.
+ *          To get elapsed time properly, you have to get the timestamp using the clock_gettime() with CLOCK_MONITONIC_RAW.
+ * @param[in] header The header handle of the rpc port parcel
+ * @param[out] timestamp The timestamp
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int rpc_port_parcel_header_get_timestamp(rpc_port_parcel_header_h header, struct timespec *timestamp);
+
+/**
  * @}
  */
 
diff --git a/src/parcel-header-internal.cc b/src/parcel-header-internal.cc
new file mode 100644 (file)
index 0000000..c1d51fb
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <atomic>
+
+#include "parcel-header-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+ParcelHeader::ParcelHeader() : seq_num_(GenerateSeqNum()) {
+  clock_gettime(CLOCK_MONOTONIC_RAW, &time_stamp_);
+}
+
+void ParcelHeader::WriteToParcel(tizen_base::Parcel* parcel) const {
+  parcel->WriteInt32(seq_num_);
+  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_sec));
+  parcel->WriteInt64(static_cast<int64_t>(time_stamp_.tv_nsec));
+}
+
+void ParcelHeader::ReadFromParcel(tizen_base::Parcel* parcel) {
+  parcel->ReadInt32(&seq_num_);
+  parcel->ReadInt64(reinterpret_cast<int64_t*>(&time_stamp_.tv_sec));
+  parcel->ReadInt64(reinterpret_cast<int64_t*>(&time_stamp_.tv_nsec));
+}
+
+void ParcelHeader::SetSeqNum(int seq_num) {
+  seq_num_ = seq_num;
+}
+
+int ParcelHeader::GetSeqNum() const {
+  return seq_num_;
+}
+
+struct timespec ParcelHeader::GetTimeStamp() const {
+  return time_stamp_;
+}
+
+int ParcelHeader::GenerateSeqNum() {
+  static std::atomic<int> num { 0 };
+  constexpr int limit = 0x3fffffff;
+  ++num;
+  return num &= limit;
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/parcel-header-internal.hh b/src/parcel-header-internal.hh
new file mode 100644 (file)
index 0000000..3519e2d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARCEL_HEADER_INTERNAL_H_
+#define PARCEL_HEADER_INTERNAL_H_
+
+#include <time.h>
+
+#include <parcel.hh>
+
+namespace rpc_port {
+namespace internal {
+
+class ParcelHeader : public tizen_base::Parcelable {
+ public:
+   ParcelHeader();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+  void SetSeqNum(int seq_num);
+  int GetSeqNum() const;
+  struct timespec GetTimeStamp() const;
+
+  static int GenerateSeqNum();
+
+ private:
+  int seq_num_;
+  struct timespec time_stamp_;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PARCEL_HEADER_INTERNAL_H_
diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc
new file mode 100644 (file)
index 0000000..ba6ba66
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include "log-private.hh"
+#include "parcel-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+Parcel::Parcel() {
+  parcel_create(&handle_);
+}
+
+Parcel::~Parcel() {
+  if (handle_)
+    parcel_destroy(handle_);
+}
+
+void Parcel::WriteToParcel(tizen_base::Parcel* parcel) const {
+  parcel->WriteParcelable(header_);
+
+  void* raw = nullptr;
+  uint32_t size = 0;
+  parcel_get_raw(handle_, &raw, &size);
+  parcel->WriteUInt32(size);
+  parcel->Write(raw, size);
+}
+
+void Parcel::ReadFromParcel(tizen_base::Parcel* parcel) {
+  parcel->ReadParcelable(&header_);
+
+  uint32_t size = 0;
+  parcel->ReadUInt32(&size);
+  if (size > 0) {
+    auto buf = new (std::nothrow) uint8_t[size];
+    if (buf == nullptr) {
+      _E("Out of memory");
+      return;
+    }
+
+    std::unique_ptr<uint8_t[]> ptr(buf);
+    parcel->Read(buf, size);
+    parcel_reset(handle_, buf, size);
+  }
+}
+
+const ParcelHeader* Parcel::GetParcelHeader() {
+  return &header_;
+}
+
+parcel_h Parcel::GetHandle() const {
+  return handle_;
+}
+
+}  // namespace internal
+}  // namespace rpc_port
diff --git a/src/parcel-internal.hh b/src/parcel-internal.hh
new file mode 100644 (file)
index 0000000..77507fb
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARCEL_INTERNAL_HH_
+#define PARCEL_INTERNAL_HH_
+
+#include <parcel.h>
+
+#include <parcelable.hh>
+
+#include "parcel-header-internal.hh"
+
+namespace rpc_port {
+namespace internal {
+
+class Parcel : public tizen_base::Parcelable {
+ public:
+   Parcel();
+   ~Parcel();
+
+  void WriteToParcel(tizen_base::Parcel* parcel) const override;
+  void ReadFromParcel(tizen_base::Parcel* parcel) override;
+
+  const ParcelHeader* GetParcelHeader();
+  parcel_h GetHandle() const;
+
+ private:
+  ParcelHeader header_;
+  parcel_h handle_ = nullptr;
+};
+
+}  // namespace internal
+}  // namespace rpc_port
+
+#endif  // PARCEL_INTERNAL_HH_
index 424d781..ded14b2 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <parcel.h>
+#include <parcel.hh>
 #include <stdint.h>
 #include <string.h>
 
@@ -22,6 +22,7 @@
 
 #include "include/rpc-port-parcel.h"
 #include "log-private.hh"
+#include "parcel-internal.hh"
 #include "port-internal.hh"
 
 #define MAX_PARCEL_SIZE   (1024 * 1024 * 10)
 
 using namespace rpc_port;
 
-static int __convert_parcel_error(int error) {
-  switch (error) {
-  case PARCEL_ERROR_ILLEGAL_BYTE_SEQ:
-  case PARCEL_ERROR_NO_DATA:
-    return RPC_PORT_ERROR_IO_ERROR;
-  case PARCEL_ERROR_OUT_OF_MEMORY:
-    return RPC_PORT_ERROR_OUT_OF_MEMORY;
-  default:
-    return RPC_PORT_ERROR_INVALID_PARAMETER;
-  }
-}
-
 RPC_API int rpc_port_parcel_create(rpc_port_parcel_h* h) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = nullptr;
-  int ret = parcel_create(&parcel);
-  if (ret != PARCEL_ERROR_NONE)
-    return __convert_parcel_error(ret);
+  auto* parcel = new (std::nothrow) internal::Parcel();
+  if (parcel == nullptr)
+    return RPC_PORT_ERROR_OUT_OF_MEMORY;
 
   *h = static_cast<rpc_port_parcel_h>(parcel);
   return RPC_PORT_ERROR_NONE;
@@ -74,7 +62,12 @@ RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h* h,
     if (len <= 0 || len > MAX_PARCEL_SIZE)
       return RPC_PORT_ERROR_IO_ERROR;
 
-    buf = new unsigned char[len];
+    buf = new (std::nothrow) unsigned char[len];
+    if (buf == nullptr) {
+      _E("Out of memory");
+      return RPC_PORT_ERROR_IO_ERROR;
+    }
+
     ret = rpc_port_read(port, buf, len);
     if (ret != 0) {
       delete[] buf;
@@ -82,14 +75,15 @@ RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h* h,
     }
   }
 
-  parcel_h parcel = nullptr;
-  int ret = parcel_create(&parcel);
-  if (ret != PARCEL_ERROR_NONE) {
+  auto* parcel = new (std::nothrow) internal::Parcel();
+  if (parcel == nullptr) {
+    _E("Out of memory");
     delete[] buf;
     return RPC_PORT_ERROR_IO_ERROR;
   }
 
-  parcel_burst_write(parcel, buf, len);
+  tizen_base::Parcel raw_parcel(buf, len);
+  raw_parcel.ReadParcelable(parcel);
   delete[] buf;
   *h = static_cast<rpc_port_parcel_h>(parcel);
   return RPC_PORT_ERROR_NONE;
@@ -99,11 +93,12 @@ RPC_API int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port) {
   if (h == nullptr || port == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  void* raw = nullptr;
-  uint32_t len = 0;
-  parcel_get_raw(parcel, &raw, &len);
-
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  tizen_base::Parcel raw_parcel;
+  raw_parcel.WriteParcelable(*parcel);
+  const std::vector<uint8_t>& raw_data = raw_parcel.GetRaw();
+  void* raw = reinterpret_cast<void*>(const_cast<uint8_t*>(&raw_data[0]));
+  uint32_t len = raw_data.size();
   if (len <= 0)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
@@ -126,8 +121,8 @@ RPC_API int rpc_port_parcel_destroy(rpc_port_parcel_h h) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_destroy(parcel);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  delete parcel;
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -135,8 +130,8 @@ RPC_API int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_byte(parcel, b);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_byte(parcel->GetHandle(), b);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -144,8 +139,8 @@ RPC_API int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_int16(parcel, i);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int16(parcel->GetHandle(), i);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -153,8 +148,8 @@ RPC_API int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_int32(parcel, i);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int32(parcel->GetHandle(), i);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -162,8 +157,8 @@ RPC_API int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_int64(parcel, i);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int64(parcel->GetHandle(), i);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -171,8 +166,8 @@ RPC_API int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_float(parcel, f);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_float(parcel->GetHandle(), f);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -180,8 +175,8 @@ RPC_API int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_double(parcel, d);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_double(parcel->GetHandle(), d);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -189,8 +184,8 @@ RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char* str) {
   if (h == nullptr || str == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_string(parcel, str);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_string(parcel->GetHandle(), str);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -198,8 +193,8 @@ RPC_API int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_bool(parcel, b);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_bool(parcel->GetHandle(), b);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -212,8 +207,8 @@ RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle* b) {
   bundle_encode(b, &raw, &len);
   auto ptr = std::unique_ptr<bundle_raw, decltype(std::free)*>(raw, std::free);
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_string(parcel, reinterpret_cast<char*>(raw));
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_string(parcel->GetHandle(), reinterpret_cast<char*>(raw));
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -221,8 +216,8 @@ RPC_API int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_write_int32(parcel, count);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_write_int32(parcel->GetHandle(), count);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -242,8 +237,8 @@ RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char* b) {
   if (h == nullptr || b == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_byte(parcel, b);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_byte(parcel->GetHandle(), b);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_byte() is failed. error(%d)", ret);
 
@@ -254,8 +249,8 @@ RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short* i) {
   if (h == nullptr || i == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_int16(parcel, i);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int16(parcel->GetHandle(), i);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_int16() is failed. error(%d)", ret);
 
@@ -266,8 +261,8 @@ RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int* i) {
   if (h == nullptr || i == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_int32(parcel, i);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int32(parcel->GetHandle(), i);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_int32() is failed. error(%d)", ret);
 
@@ -278,9 +273,9 @@ RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long* i) {
   if (h == nullptr || i == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   int64_t val = 0;
-  int ret = parcel_read_int64(parcel, &val);
+  int ret = parcel_read_int64(parcel->GetHandle(), &val);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_int64() is failed. error(%d)", ret);
 
@@ -292,8 +287,8 @@ RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float* f) {
   if (h == nullptr || f == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_float(parcel, f);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_float(parcel->GetHandle(), f);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_float() is failed. error(%d)", ret);
 
@@ -304,8 +299,8 @@ RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double* d) {
   if (h == nullptr || d == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_double(parcel, d);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_double(parcel->GetHandle(), d);
   if (ret != PARCEL_ERROR_NONE)
     _E("parcel_read_double() is failed. error(%d)", ret);
 
@@ -316,8 +311,8 @@ RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char** str) {
   if (h == nullptr || str == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_string(parcel, str);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_string(parcel->GetHandle(), str);
   if (ret != PARCEL_ERROR_NONE) {
     _E("parcel_read_string() is failed. error(%d)", ret);
     *str = strdup("");
@@ -330,9 +325,9 @@ RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool* b) {
   if (h == nullptr || b == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_bool(parcel, b);
-  if (ret != PARCEL_ERROR_NONE)
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_bool(parcel->GetHandle(), b);
+  if (ret != 0)
     _E("parcel_read_bool() is failed. error(%d)", ret);
 
   return RPC_PORT_ERROR_NONE;
@@ -342,10 +337,10 @@ RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle** b) {
   if (h == nullptr || b == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   char* raw = nullptr;
-  int ret = parcel_read_string(parcel, &raw);
-  if (ret != PARCEL_ERROR_NONE) {
+  int ret = parcel_read_string(parcel->GetHandle(), &raw);
+  if (ret != 0) {
     _E("parcel_read_string() is failed. error(%d)", ret);
     *b = bundle_create();
   } else {
@@ -360,9 +355,9 @@ RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int* count) {
   if (h == nullptr || count == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  int ret = parcel_read_int32(parcel, count);
-  if (ret != PARCEL_ERROR_NONE)
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  int ret = parcel_read_int32(parcel->GetHandle(), count);
+  if (ret != 0)
     _E("parcel_read_int32() is failed. error(%d)", ret);
 
   return RPC_PORT_ERROR_NONE;
@@ -377,7 +372,6 @@ RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h,
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
   parcelable->from(h, data);
-
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -386,11 +380,12 @@ RPC_API int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf,
   if (h == nullptr || buf == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   uint32_t valid_size = size & UINT32_MAX;
-  int ret = parcel_burst_read(parcel, static_cast<void*>(buf), valid_size);
+  int ret = parcel_burst_read(parcel->GetHandle(), static_cast<void*>(buf),
+      valid_size);
   if (ret != PARCEL_ERROR_NONE)
-    _E("parcel_burst_read() is failed. error(%d)", ret);
+    _E("parcel_read() is failed. error(%d)", ret);
 
   return RPC_PORT_ERROR_NONE;
 }
@@ -400,9 +395,10 @@ RPC_API int rpc_port_parcel_burst_write(rpc_port_parcel_h h,
   if (h == nullptr || buf == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   uint32_t valid_size = size & UINT32_MAX;
-  parcel_burst_write(parcel, static_cast<const void*>(buf), valid_size);
+  parcel_burst_write(parcel->GetHandle(), static_cast<const void*>(buf),
+      valid_size);
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -410,8 +406,8 @@ RPC_API int rpc_port_parcel_reset_reader(rpc_port_parcel_h h) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
-  parcel_reset_reader(parcel);
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  parcel_reset_reader(parcel->GetHandle());
   return RPC_PORT_ERROR_NONE;
 }
 
@@ -420,10 +416,14 @@ RPC_API int rpc_port_parcel_to_array(rpc_port_parcel_h h, void** array,
   if (h == nullptr || !array || !size)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   void* raw = nullptr;
   uint32_t raw_size = 0;
-  parcel_get_raw(parcel, &raw, &raw_size);
+  parcel_get_raw(parcel->GetHandle(), &raw, &raw_size);
+  if (raw_size == 0) {
+    _E("raw_size is zero");
+    return RPC_PORT_ERROR_IO_ERROR;
+  }
 
   void* array_ptr = malloc(raw_size);
   if (array_ptr == nullptr)
@@ -437,11 +437,53 @@ RPC_API int rpc_port_parcel_to_array(rpc_port_parcel_h h, void** array,
 
 RPC_API int rpc_port_parcel_from_array(rpc_port_parcel_h h, const void* array,
     unsigned int size) {
-  if (h == nullptr || !array || size == 0)
+  if (h == nullptr || array == nullptr || size == 0)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
 
-  parcel_h parcel = static_cast<parcel_h>(h);
+  auto* parcel = static_cast<internal::Parcel*>(h);
   uint32_t valid_size = size & UINT32_MAX;
-  parcel_reset(parcel, array, valid_size);
+  parcel_reset(parcel->GetHandle(), array, valid_size);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_get_header(rpc_port_parcel_h h,
+    rpc_port_parcel_header_h* header) {
+  if (h == nullptr || header == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel = static_cast<internal::Parcel*>(h);
+  auto* parcel_header = parcel->GetParcelHeader();
+  *header = reinterpret_cast<rpc_port_parcel_header_h>(
+      const_cast<internal::ParcelHeader*>(parcel_header));
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_set_seq_num(rpc_port_parcel_header_h header,
+    int seq_num) {
+  if (header == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  parcel_header->SetSeqNum(seq_num);
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_get_seq_num(rpc_port_parcel_header_h header,
+    int* seq_num) {
+  if (header == nullptr || seq_num == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  *seq_num = parcel_header->GetSeqNum();
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_header_get_timestamp(
+    rpc_port_parcel_header_h header, struct timespec* timestamp) {
+  if (header == nullptr || timestamp == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto* parcel_header = static_cast<internal::ParcelHeader*>(header);
+  *timestamp = parcel_header->GetTimeStamp();
   return RPC_PORT_ERROR_NONE;
 }
index 2b67502..79bb7dd 100644 (file)
@@ -320,3 +320,85 @@ TEST_F(ParcelTest, rpc_port_parcel_burst_read_write_P) {
     ASSERT_EQ(buf[i], buf2[i]);
   }
 }
+
+/*
+ * @testcase rpc_port_parcel_get_header_P
+ * @description Gets the header handle from the rpc port parcel handle
+ * @apicovered rpc_port_parcel_get_header
+ */
+TEST_F(ParcelTest, rpc_port_parcel_get_header_P) {
+  rpc_port_parcel_header_h header = nullptr;
+  int ret = rpc_port_parcel_get_header(handle_, &header);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+  ASSERT_NE(header, nullptr);
+}
+
+/*
+ * @testcase rpc_port_parcel_get_header_N
+ * @description Gets the header handle from the rpc port parcel handle
+ * @apicovered rpc_port_parcel_get_header
+ */
+TEST_F(ParcelTest, rpc_port_parcel_get_header_N) {
+  int ret = rpc_port_parcel_get_header(nullptr, nullptr);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER);
+}
+
+/*
+ * @testcase rpc_port_parcel_header_set_get_seq_num_P
+ * @description Sets and Gets the sequence number
+ * @apicovered rpc_port_parcel_header_set_seq_num, rpc_port_parcel_header_get_seq_num
+ */
+TEST_F(ParcelTest, rpc_port_parcel_header_set_get_seq_num_P) {
+  rpc_port_parcel_header_h header = nullptr;
+  int ret = rpc_port_parcel_get_header(handle_, &header);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+
+  ret = rpc_port_parcel_header_set_seq_num(header, 100);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+
+  int seq_num = 0;
+  ret = rpc_port_parcel_header_get_seq_num(header, &seq_num);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+  ASSERT_EQ(seq_num, 100);
+}
+
+/*
+ * @testcase rpc_port_parcel_header_set_get_seq_num_N
+ * @description Sets and Gets the sequence number
+ * @apicovered rpc_port_parcel_header_set_seq_num, rpc_port_parcel_header_get_seq_num
+ */
+TEST_F(ParcelTest, rpc_port_parcel_header_set_get_seq_num_N) {
+  int ret = rpc_port_parcel_header_set_seq_num(nullptr, -1);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER);
+
+  ret = rpc_port_parcel_header_get_seq_num(nullptr, nullptr);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER);
+}
+
+/*
+ * @testcase rpc_port_parcel_header_get_timestamp_P
+ * @description Gets the timestamp from the header handle of the rpc port parcel
+ * @apicovered rpc_port_parcel_header_get_timestamp
+ */
+TEST_F(ParcelTest, rpc_port_parcel_header_get_timestamp_P) {
+  rpc_port_parcel_header_h header = nullptr;
+  int ret = rpc_port_parcel_get_header(handle_, &header);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+
+  struct timespec timestamp = { 0, };
+  ret = rpc_port_parcel_header_get_timestamp(header, &timestamp);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_NONE);
+
+  ASSERT_NE(timestamp.tv_sec, 0);
+  ASSERT_NE(timestamp.tv_nsec, 0);
+}
+
+/*
+ * @testcase rpc_port_parcel_header_get_timestamp_N
+ * @description Gets the timestamp from the header handle of the rpc port parcel
+ * @apicovered rpc_port_parcel_header_get_timestamp
+ */
+TEST_F(ParcelTest, rpc_port_parcel_header_get_timestamp_N) {
+  int ret = rpc_port_parcel_header_get_timestamp(nullptr, nullptr);
+  ASSERT_EQ(ret, RPC_PORT_ERROR_INVALID_PARAMETER);
+}