Modify doxygen comments 70/180870/8
authorInkyun Kil <inkyun.kil@samsung.com>
Mon, 4 Jun 2018 00:13:46 +0000 (09:13 +0900)
committerJunghoon Park <jh9216.park@samsung.com>
Mon, 18 Jun 2018 05:10:21 +0000 (14:10 +0900)
- Add new APIs to fix performance issue and multi-thread issue

Change-Id: I56deab83f106f10746bc9fbb33883fef271a9fcf
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
Signed-off-by: Junghoon Park <jh9216.park@samsung.com>
13 files changed:
include/rpc-port-parcel.h
include/rpc-port.h
src/fdbroker-internal.cc
src/fdbroker-internal.h
src/parcel-internal.cc
src/parcel-internal.h
src/proxy-internal.cc
src/proxy-internal.h
src/rpc-port-parcel.cc
src/rpc-port.cc
src/stub-internal.cc
src/stub-internal.h
unit_tests/src/rpc_port_parcel_test.cc

index 715d020..4ba9f9f 100644 (file)
@@ -32,13 +32,13 @@ extern "C" {
 
 /**
  * @brief The rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef void *rpc_port_parcel_h;
 
 /**
  * @brief The interface for converting data to/from a parcel.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef struct __rpc_port_parcelable {
        void (*to)(rpc_port_parcel_h h, void *data);
@@ -47,7 +47,7 @@ typedef struct __rpc_port_parcelable {
 
 /**
  * @brief Creates a rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks You must release @a h using rpc_port_parcel_destroy().
  * @param[out] h The rpc port parcel handle that is newly created
  * @return @c 0 on success,
@@ -61,7 +61,7 @@ int rpc_port_parcel_create(rpc_port_parcel_h *h);
  * @brief Creates a rpc port parcel handle from port.
  * @details Creates a rpc port parcel handle using read data from the port.
  *          It calls rpc_port_read() internally.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks You must release @a h using rpc_port_parcel_destroy().
  * @param[out] h The rpc port parcel handle that is newly created
  * @param[in] port The rpc port handle for creating handle
@@ -79,7 +79,7 @@ int rpc_port_parcel_create_from_port(rpc_port_parcel_h *h, rpc_port_h port);
  * @brief Sends parcel data through the port.
  * @details Sends parcel data through the port. It calls rpc_port_write()
  *          internally.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle that is newly created
  * @param[in] port The rpc port handle for writing data
  * @return @c 0 on success,
@@ -93,7 +93,7 @@ int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port);
 
 /**
  * @brief Destroys a rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -105,7 +105,7 @@ int rpc_port_parcel_destroy(rpc_port_parcel_h h);
 
 /**
  * @brief Writes a byte value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] b Byte data
  * @return @c 0 on success,
@@ -118,7 +118,7 @@ int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b);
 
 /**
  * @brief Writes a short value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] i short data
  * @return @c 0 on success,
@@ -131,7 +131,7 @@ int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i);
 
 /**
  * @brief Writes a integer value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] i int data
  * @return @c 0 on success,
@@ -144,7 +144,7 @@ int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i);
 
 /**
  * @brief Writes a long long integer value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] i long long data
  * @return @c 0 on success,
@@ -157,7 +157,7 @@ int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i);
 
 /**
  * @brief Writes a floating point value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] f float data
  * @return @c 0 on success,
@@ -170,7 +170,7 @@ int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f);
 
 /**
  * @brief Writes a double precision floating point value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] d double data
  * @return @c 0 on success,
@@ -183,7 +183,7 @@ int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d);
 
 /**
  * @brief Writes a string value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] str string data
  * @return @c 0 on success,
@@ -196,7 +196,7 @@ int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char *str);
 
 /**
  * @brief Writes a boolean value into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] b boolean data
  * @return @c 0 on success,
@@ -209,7 +209,7 @@ int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b);
 
 /**
  * @brief Writes a bundle data into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] b Bundle data
  * @return @c 0 on success,
@@ -222,7 +222,7 @@ int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle *b);
 
 /**
  * @brief Writes a count for array into rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] count Array count
  * @return @c 0 on success,
@@ -235,7 +235,7 @@ int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count);
 
 /**
  * @brief Writes the data into parcel handle using @a parcelable.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] parcelable The interface to write the data into parcel handle
  * @param[in] data Data which write into parcel
@@ -249,7 +249,7 @@ int rpc_port_parcel_write(rpc_port_parcel_h h, rpc_port_parcelable_t *parcelable
 
 /**
  * @brief Reads a byte value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] b Byte data
  * @return @c 0 on success,
@@ -262,7 +262,7 @@ int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char *b);
 
 /**
  * @brief Reads a short value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] i short data
  * @return @c 0 on success,
@@ -275,7 +275,7 @@ int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short *i);
 
 /**
  * @brief Reads a integer value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] i int data
  * @return @c 0 on success,
@@ -288,7 +288,7 @@ int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int *i);
 
 /**
  * @brief Reads a long long integer value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] i long long data
  * @return @c 0 on success,
@@ -301,7 +301,7 @@ int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long *i);
 
 /**
  * @brief Reads a floating point value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] f float data
  * @return @c 0 on success,
@@ -314,7 +314,7 @@ int rpc_port_parcel_read_float(rpc_port_parcel_h h, float *f);
 
 /**
  * @brief Reads a double precision floating point value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] d double data
  * @return @c 0 on success,
@@ -327,7 +327,7 @@ int rpc_port_parcel_read_double(rpc_port_parcel_h h, double *d);
 
 /**
  * @brief Reads a string value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks The @a str should be released using free().
  * @param[in] h The rpc port parcel handle
  * @param[out] str string data
@@ -341,7 +341,7 @@ int rpc_port_parcel_read_string(rpc_port_parcel_h h, char **str);
 
 /**
  * @brief Reads a boolean value from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] b boolean data
  * @return @c 0 on success,
@@ -354,7 +354,7 @@ int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool *b);
 
 /**
  * @brief Reads a bundle data from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks The @a b should be released using bundle_free().
  * @param[in] h The rpc port parcel handle
  * @param[out] b Bundle data
@@ -368,7 +368,7 @@ int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle **b);
 
 /**
  * @brief Reads a count for array from rpc port parcel handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[out] count Array count
  * @return @c 0 on success,
@@ -381,7 +381,7 @@ int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int *count);
 
 /**
  * @brief Reads a parcel from the data using @a parcelable.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port parcel handle
  * @param[in] parcelable The interface to get data from parcel handle
  * @param[in] data Data which get from parcel
@@ -393,6 +393,35 @@ int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int *count);
  */
 int rpc_port_parcel_read(rpc_port_parcel_h h, rpc_port_parcelable_t *parcelable, void *data);
 
+
+/**
+ * @brief Reads bytes from rpc port parcel handle.
+ * @since_tizen 4.0
+ * @param[in] h The rpc port parcel handle
+ * @param[out] buf The array buffer to read
+ * @param[in] size Bytes to read
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER The specified @a h is NULL
+ * @see rpc_port_parcel_write_bool()
+ */
+int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf, unsigned int size);
+
+/**
+ * @brief Write bytes to rpc port parcel handle.
+ * @since_tizen 4.0
+ * @param[in] h The rpc port parcel handle
+ * @param[in] buf The array buffer to write
+ * @param[in] size Bytes to write
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER The specified @a h is NULL
+ * @see rpc_port_parcel_write_bool()
+ */
+int rpc_port_parcel_burst_write(rpc_port_parcel_h h, const unsigned char *buf, unsigned int size);
+
 /**
  * @}
  */
index d4f3de0..f14aac0 100755 (executable)
@@ -32,7 +32,7 @@ extern "C" {
 
 /**
  * @brief Enumeration for error codes of a rpc port.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef enum {
        RPC_PORT_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
@@ -42,17 +42,26 @@ typedef enum {
        RPC_PORT_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
 } rpc_port_error_e;
 
+/**
+ * @brief Enumeration for types of communication channels.
+ * @since_tizen 4.0
+ */
+typedef enum {
+       RPC_PORT_PORT_MAIN, /**< Main channel */
+       RPC_PORT_PORT_CALLBACK, /**< The channel for callbacks */
+} rpc_port_port_type_e;
+
 /* Common */
 
 /**
  * @brief The rpc port handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef void *rpc_port_h;
 
 /**
  * @brief Reads data from an RPC port.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  *
  * @param[in] h The rpc port handle
  * @param[out] buf Buffer for reading data
@@ -69,7 +78,7 @@ int rpc_port_read(rpc_port_h h, void *buf, unsigned int size);
 
 /**
  * @brief Writes data to an RPC port.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  *
  * @param[in] h The rpc port handle
  * @param[in] buf Buffer for writing data
@@ -90,7 +99,7 @@ int rpc_port_write(rpc_port_h h, const void *buf, unsigned int size);
 /**
  * @brief Called when the proxy is connected.
  * @details The function is called when the proxy is connected with stub by port.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] receiver The target stub app id
  * @param[in] port_name The name of the port
  * @param[in] port The rpc port handle for reading and writing
@@ -102,7 +111,7 @@ typedef void (*rpc_port_proxy_connected_event_cb)(const char *receiver,
 /**
  * @brief Called when the proxy is disconnected.
  * @details The function is called when the proxy is disconnected from stub.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] receiver The target stub app id
  * @param[in] port_name The name of the port
  * @param[in] user_data The user data passed from the register function
@@ -113,7 +122,7 @@ typedef void (*rpc_port_proxy_disconnected_event_cb)(const char *receiver,
 /**
  * @brief Called when the proxy is rejected.
  * @details The function is called when the proxy is rejected to connect stub.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] receiver The target stub app id
  * @param[in] port_name The name of the port
  * @param[in] user_data The user data passed from the register function
@@ -124,7 +133,7 @@ typedef void (*rpc_port_proxy_rejected_event_cb)(const char *receiver,
 /**
  * @brief Called when the proxy received data.
  * @details The function is called when the proxy received data from stub.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] receiver The target stub app id
  * @param[in] port_name The name of the port
  * @param[in] user_data The user data passed from the register function
@@ -134,13 +143,13 @@ typedef void (*rpc_port_proxy_received_event_cb)(const char *receiver,
 
 /**
  * @brief The rpc port proxy handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef void *rpc_port_proxy_h;
 
 /**
  * @brief Creates a rpc port proxy handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks You must release @a h using rpc_port_proxy_destroy().
  * @param[out] h The rpc port proxy handle that is newly created
  * @return @c 0 on success,
@@ -153,7 +162,7 @@ int rpc_port_proxy_create(rpc_port_proxy_h *h);
 
 /**
  * @brief Destroys a rpc port proxy handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port proxy handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -166,7 +175,7 @@ int rpc_port_proxy_destroy(rpc_port_proxy_h h);
 /**
  * @brief Connects to @a port of @a appid.
  * @details To send and receive data, the proxy should connect to port of stub
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @privlevel public
  * @privilege %http://tizen.org/privilege/appmanager.launch \n
  *            %http://tizen.org/privilege/datasharing
@@ -186,7 +195,7 @@ int rpc_port_proxy_connect(rpc_port_proxy_h h, const char *appid,
 
 /**
  * @brief Adds a proxy connected callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port proxy handle
  * @param[in] cb The callback function to be called when proxy is connected
  * @param[in] user_data The user data to be passed to
@@ -201,7 +210,7 @@ int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h,
 
 /**
  * @brief Adds a proxy disconnected callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port proxy handle
  * @param[in] cb The callback function to be called when proxy is disconnected
  * @param[in] user_data The user data to be passed to
@@ -216,7 +225,7 @@ int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h,
 
 /**
  * @brief Adds a proxy rejected callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port proxy handle
  * @param[in] cb The callback function to be called when proxy is rejected
  * @param[in] user_data The user data to be passed to
@@ -231,7 +240,7 @@ int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h,
 
 /**
  * @brief Adds a proxy received callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port proxy handle
  * @param[in] cb The callback function to be called when proxy received data
  * @param[in] user_data The user data to be passed to
@@ -244,11 +253,31 @@ int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h,
 int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h,
                rpc_port_proxy_received_event_cb cb, void *user_data);
 
+/**
+ * @brief Gets a port from proxy handle.
+ * @since_tizen 4.0
+ * @remarks This handle @a port will not be valid if the proxy was disconnected or destroyed.
+ * @param[in] h The rpc port proxy handle
+ * @param[in] type The type of port
+ * @param[out] port The port to communicate
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER The specified @a h is NULL
+ * @retval #RPC_PORT_ERROR_IO_ERROR No available ports
+ * @see rpc_port_write()
+ * @see rpc_port_read()
+ * @see rpc_port_parcel_create_from_port()
+ * @see rpc_port_parcel_send();
+ */
+int rpc_port_proxy_get_port(rpc_port_proxy_h h, rpc_port_port_type_e type,
+               rpc_port_h *port);
+
 /* Stub */
 
 /**
  * @brief The rpc port stub handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  */
 typedef void *rpc_port_stub_h;
 
@@ -257,7 +286,7 @@ typedef void *rpc_port_stub_h;
  * @details The function is called when the proxy is connected with stub.
  *          When a proxy connects to stub several times with new port,
  *          you can handle each request by using @a instance.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] sender The target proxy app id
  * @param[in] instance The information of the request
  * @param[in] user_data The user data passed from the register function
@@ -270,7 +299,7 @@ typedef void (*rpc_port_stub_connected_event_cb)(const char *sender,
  * @details The function is called when the proxy is disconnected from stub.
  *          When a proxy is disconnected, you can check the request
  *          by using @a instance.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] sender The target proxy app id
  * @param[in] instance The information of the request
  * @param[in] user_data The user data passed from the register function
@@ -284,7 +313,7 @@ typedef void (*rpc_port_stub_disconnected_event_cb)(const char *sender,
  *          When a stub received data from several ports, you can handle
  *          each request by using @a instance. If the function returns non zero
  *          value, the stub is disconnected.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] sender The target proxy app id
  * @param[in] instance The information of the request
  * @param[in] port The rpc port handle for reading and writing
@@ -297,7 +326,7 @@ typedef int (*rpc_port_stub_received_event_cb)(const char *sender,
 
 /**
  * @brief Creates a rpc port stub handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @remarks You must release @a h using rpc_port_stub_destroy().
  * @param[out] h The rpc port stub handle that is newly created
  * @param[in] port_name The name of the port which want to listen
@@ -311,7 +340,7 @@ int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name);
 
 /**
  * @brief Destroys a rpc port stub handle.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -324,7 +353,7 @@ int rpc_port_stub_destroy(rpc_port_stub_h h);
 /**
  * @brief Listens to the requests for connections.
  * @details The stub listens requests to connect by port
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @return @c 0 on success,
  *         otherwise a negative error value
@@ -338,7 +367,7 @@ int rpc_port_stub_listen(rpc_port_stub_h h);
  * @brief Adds a privilege to the stub.
  * @details The stub can control access to the port using tizen privilege.
  *          It allows connections only if the proxy which have the privileges.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @param[in] privilege The privilege to access this stub
  * @return @c 0 on success,
@@ -353,7 +382,7 @@ int rpc_port_stub_add_privilege(rpc_port_stub_h h, const char *privilege);
  * @details The stub can control access to the port using tizen certificate.
  *          It allows connections only if the proxy is signed with the same
  *          certificate.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @param[in] trusted Whether stub allows only trusted proxy or not
  * @return @c 0 on success,
@@ -365,7 +394,7 @@ int rpc_port_stub_set_trusted(rpc_port_stub_h h, const bool trusted);
 
 /**
  * @brief Adds a stub connected callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc stub stub handle
  * @param[in] cb The callback function to be called when proxy is connected
  *               with the stub
@@ -381,7 +410,7 @@ int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h,
 
 /**
  * @brief Adds a stub disconnected callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @param[in] cb The callback function to be called when proxy is disconnected
  *               with the stub
@@ -397,7 +426,7 @@ int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h,
 
 /**
  * @brief Adds a stub received callback.
- * @since_tizen 5.0
+ * @since_tizen 4.0
  * @param[in] h The rpc port stub handle
  * @param[in] cb The callback function to be called when stub received data
  * @param[in] user_data The user data to be passed to
@@ -411,6 +440,27 @@ int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h,
                rpc_port_stub_received_event_cb cb, void *user_data);
 
 /**
+ * @brief Gets a port from stub handle.
+ * @since_tizen 4.0
+ * @remarks This handle @a port will not be valid if the instance of the stub was disconnected or destroyed.
+ * @param[in] h The rpc port stub handle
+ * @param[in] type The type of port
+ * @param[in] instance The ID of the instance which is connected
+ * @param[out] port The port to communicate
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #RPC_PORT_ERROR_NONE Successful
+ * @retval #RPC_PORT_ERROR_INVALID_PARAMETER The specified @a h is NULL
+ * @retval #RPC_PORT_ERROR_IO_ERROR No available ports
+ * @see rpc_port_write()
+ * @see rpc_port_read()
+ * @see rpc_port_parcel_create_from_port()
+ * @see rpc_port_parcel_send();
+ */
+int rpc_port_stub_get_port(rpc_port_stub_h h, rpc_port_port_type_e type,
+               const char *instance, rpc_port_h *port);
+
+/**
  * @}
  */
 
index 0dce2cf..36df52d 100644 (file)
@@ -99,11 +99,11 @@ FdBroker::DBusMock& FdBroker::DBusMock::GetInst() {
 }
 
 int FdBroker::DBusMock::Send(const std::string& sender,
-                              const std::string& port, int fd) {
+                             const std::string& port, int fds[2]) {
   if (ports_.find(port) == ports_.end())
     return -1;
 
-  ports_[port]->OnFdReceived(sender, fd);
+  ports_[port]->OnFdReceived(sender, fds);
   return 0;
 }
 
@@ -221,13 +221,15 @@ std::string FdBroker::GetInterfaceName(const std::string& target_appid,
 }
 
 int FdBroker::Send(const std::string& target_appid,
-                   const std::string& port_name) {
+                   const std::string& port_name,
+                   int (*fds)[2]) {
   std::string interface_name = GetInterfaceName(target_appid, port_name);
   GDBusMessage *msg;
   GDBusMessage *reply;
   GError *err = nullptr;
   GVariant *reply_body;
-  SocketPair sock_pair(mock_);
+  SocketPair main_sock_pair(mock_);
+  SocketPair delegate_sock_pair(mock_);
   FdList fd_list;
   char sender_appid[255];
   int ret;
@@ -238,19 +240,24 @@ int FdBroker::Send(const std::string& target_appid,
     return -1;
   }
 
-  if (sock_pair.Request() != 0)
+  if (main_sock_pair.Request() != 0)
+    return -1;
+  if (delegate_sock_pair.Request() != 0)
     return -1;
 
   if (mock_) {
-    int ret = DBusMock::GetInst().Send("TestApp", port_name,
-                             sock_pair.Detach(SocketPair::RECEIVER));
+    (*fds)[0] = main_sock_pair.Detach(SocketPair::RECEIVER);
+    (*fds)[1] = delegate_sock_pair.Detach(SocketPair::RECEIVER);
+    int ret = DBusMock::GetInst().Send("TestApp", port_name, *fds);
     if (ret < 0)
       return ret;
 
-    return sock_pair.Detach(SocketPair::SENDER);
+    return main_sock_pair.Detach(SocketPair::SENDER);
   }
 
-  if (fd_list.Add(sock_pair.Detach(SocketPair::RECEIVER)) != 0)
+  if (fd_list.Add(main_sock_pair.Detach(SocketPair::RECEIVER)) != 0)
+    return -1;
+  if (fd_list.Add(delegate_sock_pair.Detach(SocketPair::RECEIVER)) != 0)
     return -1;
 
   msg = g_dbus_message_new_method_call(interface_name.c_str(),
@@ -290,17 +297,18 @@ int FdBroker::Send(const std::string& target_appid,
 
   LOGD("[Reply : %d]", ret);
 
-  int fd = sock_pair.Detach(SocketPair::SENDER);
+  (*fds)[0] = main_sock_pair.Detach(SocketPair::SENDER);
+  (*fds)[1] = delegate_sock_pair.Detach(SocketPair::SENDER);
   g_object_unref(msg);
 
-  return fd;
+  return (*fds)[0];
 }
 
 void FdBroker::ReceiveMessage(const char* sender_appid,
                               GDBusMethodInvocation* invocation) {
   GDBusMessage* msg;
   GUnixFDList* fd_list;
-  int fd_len;
+  int fd_len = 0;
   int* returned_fds = nullptr;
 
   msg = g_dbus_method_invocation_get_message(invocation);
@@ -310,12 +318,12 @@ void FdBroker::ReceiveMessage(const char* sender_appid,
     return;
 
   returned_fds = g_unix_fd_list_steal_fds(fd_list, &fd_len);
-  if (returned_fds == nullptr) {
-    LOGE("fail to get fds");
+  if (returned_fds == nullptr || fd_len != 2) {
+    LOGE("fail to get fds. fd_len(%d)", fd_len);
     return;
   }
 
-  listener_->OnFdReceived(sender_appid, returned_fds[0]);
+  listener_->OnFdReceived(sender_appid, returned_fds);
   free(returned_fds);
 }
 
index 3dd43d6..e9b15b8 100644 (file)
@@ -36,7 +36,7 @@ class FdBroker {
  public:
   class IEventListener {
    public:
-    virtual void OnFdReceived(const std::string& sender, int fd) = 0;
+    virtual void OnFdReceived(const std::string& sender, int fds[2]) = 0;
   };
 
   class IEventWatcher {
@@ -55,7 +55,8 @@ class FdBroker {
     DBusConnectionManager::GetInst().Dispose();
   }
 
-  int Send(const std::string& target_appid, const std::string& port_name);
+  int Send(const std::string& target_appid, const std::string& port_name,
+           int (*fds)[2]);
   int Listen(IEventListener* ev, const std::string& port_name);
   AccessController& GetAccessController();
   int Watch(IEventWatcher* ev, const std::string& target_appid,
@@ -89,7 +90,7 @@ class FdBroker {
     DBusMock& operator = (const DBusMock&) = delete;
 
     static DBusMock& GetInst();
-    int Send(const std::string& sender, const std::string& port, int fd);
+    int Send(const std::string& sender, const std::string& port, int fds[2]);
     int AddListener(const std::string& port,
                     FdBroker::IEventListener* listener);
     int Watch(FdBroker::IEventWatcher* watcher, const std::string& target_appid,
index e568f90..cae8988 100644 (file)
@@ -128,4 +128,13 @@ const std::vector<unsigned char>& Parcel::GetRaw() {
   return data_;
 }
 
+void Parcel::Write(const unsigned char* buf, unsigned int size) {
+  std::copy(buf, buf + size, std::back_inserter(data_));
+}
+
+void Parcel::Read(unsigned char* buf, unsigned int size) {
+  std::copy(&data_[reader_], &data_[reader_] + size, buf);
+  reader_ += size;
+}
+
 }  // namespace rpc_port
index 6fc314a..3b491d0 100644 (file)
@@ -31,6 +31,8 @@ class Parcel {
   Parcel() = default;
   Parcel(const unsigned char* buf, unsigned int size);
 
+  void Write(const unsigned char* buf, unsigned int size);
+  void Read(unsigned char* buf, unsigned int size);
   void WriteByte(char b);
   void WriteInt16(short i);
   void WriteInt32(int i);
index 593ca7e..f5bd629 100644 (file)
@@ -40,25 +40,24 @@ Proxy::Proxy(bool mock)
 
 Proxy::~Proxy() {
   LOGD("Proxy::~Proxy");
-  if (src_ > 0)
-    g_source_remove(src_);
-
-  if (disconn_src_ > 0)
-    g_source_remove(disconn_src_);
-
-  if (gioc_ != nullptr)
-    g_io_channel_unref(gioc_);
 }
 
 gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond,
                                      gpointer data) {
   Proxy* proxy = static_cast<Proxy*>(data);
   IEventListener* listener = proxy->listener_;
+  int fd = g_io_channel_unix_get_fd(gio);
+
+  LOGW("Socket was disconnected. fd(%d)", fd);
+
+  if (proxy->main_port_.get()->GetFd() == fd) {
+    proxy->listener_ = nullptr;
+    proxy->main_port_.get()->SetDisconnectedSource(0);
+    listener->OnDisconnected(proxy->target_appid_);
+  } else if (proxy->delegate_port_.get()->GetFd() == fd) {
+    proxy->delegate_port_.get()->SetDisconnectedSource(0);
+  }
 
-  LOGW("Socket was disconnected");
-  proxy->listener_ = nullptr;
-  proxy->disconn_src_ = 0;
-  listener->OnDisconnected(proxy->target_appid_);
   return FALSE;
 }
 
@@ -68,54 +67,22 @@ gboolean Proxy::OnDataReceived(GIOChannel *gio, GIOCondition cond,
   int fd = g_io_channel_unix_get_fd(gio);
   char buffer[4];
 
-  if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
-    LOGW("Socket was disconnected by stub");
-    IEventListener* listener = proxy->listener_;
-    proxy->listener_ = nullptr;
-    proxy->src_ = 0;
-    listener->OnDisconnected(proxy->target_appid_);
-    return FALSE;
+  if (proxy->main_port_.get()->GetFd() == fd) {
+    if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
+      LOGW("Socket was disconnected by stub. fd(%d)", fd);
+      IEventListener* listener = proxy->listener_;
+      proxy->listener_ = nullptr;
+      proxy->main_port_.get()->SetSource(0);
+      listener->OnDisconnected(proxy->target_appid_);
+      return FALSE;
+    }
+
+    proxy->listener_->OnReceived(proxy->target_appid_);
   }
 
-  proxy->listener_->OnReceived(proxy->target_appid_);
-
   return TRUE;
 }
 
-int Proxy::Watch(int fd) {
-  char buf[1024];
-
-  gioc_ = g_io_channel_unix_new(fd);
-  if (!gioc_) {
-    LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf)));
-    return -1;
-  }
-
-  disconn_src_ = g_io_add_watch(gioc_,
-                                (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
-                                OnSocketDisconnected, this);
-  if (disconn_src_ == 0) {
-    LOGE("fail to add watch on socket");
-    g_io_channel_unref(gioc_);
-    gioc_ = nullptr;
-    return -1;
-  }
-
-  src_ = g_io_add_watch(gioc_,
-                        (GIOCondition)(G_IO_IN),
-                        OnDataReceived, this);
-  if (src_ == 0) {
-    LOGE("fail to add watch on socket");
-    g_source_remove(disconn_src_);
-    disconn_src_ = 0;
-    g_io_channel_unref(gioc_);
-    gioc_ = nullptr;
-    return -1;
-  }
-
-  return 0;
-}
-
 void Proxy::OnPortRejected(const std::string& appid) {
   if (listener_ == nullptr)
     return;
@@ -132,17 +99,19 @@ void Proxy::OnPortAppeared(const std::string& appid,
   if (listener_ == nullptr)
     return;
 
-  int fd = fd_broker_.Send(appid, port_name);
-  if (fd <= 0) {
+  int fds[2] = { 0, };
+  int r = fd_broker_.Send(appid, port_name, &fds);
+  if (r <= 0 || fds[0] <= 0 || fds[1] <= 0) {
     IEventListener* listener = listener_;
     listener_ = nullptr;
     listener->OnRejected(appid);
     return;
   }
 
-  port_.reset(new Port(fd, port_name));
-  listener_->OnConnected(appid, port_.get());
-  Watch(fd);
+  LOGW("[__OnPortAppeared__] fds[0]: %d, fds[1]: %d", fds[0], fds[1]);
+  main_port_.reset(new ProxyPort(this, fds[0], appid));
+  delegate_port_.reset(new ProxyPort(this, fds[1], appid));
+  listener_->OnConnected(appid, main_port_.get());
 }
 
 void Proxy::OnPortVanished(const std::string& appid,
@@ -175,5 +144,64 @@ int Proxy::Connect(const std::string appid, const std::string& port_name,
   return RPC_PORT_ERROR_NONE;
 }
 
+Proxy::ProxyPort::ProxyPort(Proxy* parent, int fd, const std::string& id)
+    : Port(fd, id), parent_(parent) {
+  Watch();
+}
+
+Proxy::ProxyPort::~ProxyPort() {
+  if (disconn_src_ > 0)
+    g_source_remove(disconn_src_);
+
+  if (src_ > 0)
+    g_source_remove(src_);
+
+  if (gioc_ != nullptr)
+    g_io_channel_unref(gioc_);
+}
+
+int Proxy::ProxyPort::Watch() {
+  char buf[1024];
+  int fd = GetFd();
+
+  gioc_ = g_io_channel_unix_new(fd);
+  if (!gioc_) {
+    LOGE("Error is %s", strerror_r(errno, buf, sizeof(buf)));
+    return -1;
+  }
+
+  disconn_src_ = g_io_add_watch(gioc_,
+      (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+      Proxy::OnSocketDisconnected, parent_);
+  if (disconn_src_ == 0) {
+    LOGE("Failed to add watch on socket");
+    g_io_channel_unref(gioc_);
+    gioc_ = nullptr;
+    return -1;
+  }
+
+  src_ = g_io_add_watch(gioc_,
+      (GIOCondition)(G_IO_IN),
+      Proxy::OnDataReceived, parent_);
+  if (src_ == 0) {
+    LOGE("Failed to add watch on socket");
+    g_source_remove(disconn_src_);
+    disconn_src_ = 0;
+    g_io_channel_unref(gioc_);
+    gioc_ = nullptr;
+    return -1;
+  }
+
+  return 0;
+}
+
+void Proxy::ProxyPort::SetDisconnectedSource(int sourceId) {
+  disconn_src_ = sourceId;
+}
+
+void Proxy::ProxyPort::SetSource(int sourceId) {
+  disconn_src_ = sourceId;
+}
+
 }  // namespace internal
 }  // namespace rpc_port
index 876bc43..b053d84 100644 (file)
@@ -46,7 +46,10 @@ class Proxy : public FdBroker::IEventWatcher {
   int Connect(const std::string appid, const std::string& port_name,
                IEventListener* ev);
   std::shared_ptr<Port> GetPort() const {
-    return port_;
+    return main_port_;
+  }
+  std::shared_ptr<Port> GetDelegatePort() const {
+    return delegate_port_;
   }
 
   const std::string& GetPortName() {
@@ -54,11 +57,28 @@ class Proxy : public FdBroker::IEventWatcher {
   }
 
  private:
+  class ProxyPort : public Port {
+   public:
+    ProxyPort(Proxy* parent, int fd, const std::string& id);
+    virtual ~ProxyPort();
+    void SetDisconnectedSource(int sourceId);
+    void SetSource(int sourceId);
+
+   private:
+    int Watch();
+
+   private:
+    GIOChannel* gioc_ = nullptr;
+    int disconn_src_ = 0;
+    int src_ = 0;
+    Proxy* parent_ = nullptr;
+  };
+
+ private:
   static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond,
                                        gpointer data);
   static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond,
                                  gpointer data);
-  int Watch(int fd);
   void OnPortAppeared(const std::string& appid,
                       const std::string& port_name) override;
   void OnPortVanished(const std::string& appid,
@@ -67,13 +87,11 @@ class Proxy : public FdBroker::IEventWatcher {
 
  private:
   std::string port_name_;
-  std::shared_ptr<Port> port_;
+  std::shared_ptr<ProxyPort> main_port_;
+  std::shared_ptr<ProxyPort> delegate_port_;
   IEventListener* listener_ = nullptr;
   FdBroker fd_broker_;
   std::string target_appid_;
-  GIOChannel* gioc_ = nullptr;
-  int disconn_src_ = 0;
-  int src_ = 0;
 };
 
 }  // namespace internal
index 8888579..307808a 100755 (executable)
@@ -348,3 +348,27 @@ RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h,
 
   return RPC_PORT_ERROR_NONE;
 }
+
+RPC_API int rpc_port_parcel_burst_read(rpc_port_parcel_h h, unsigned char *buf,
+    unsigned int size) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  Parcel* p = static_cast<Parcel*>(h);
+
+  p->Read(buf, size);
+
+  return RPC_PORT_ERROR_NONE;
+}
+
+RPC_API int rpc_port_parcel_burst_write(rpc_port_parcel_h h,
+    const unsigned char *buf, unsigned int size) {
+  if (h == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  Parcel* p = static_cast<Parcel*>(h);
+
+  p->Write(buf, size);
+
+  return RPC_PORT_ERROR_NONE;
+}
index 958e378..48d7518 100755 (executable)
@@ -280,6 +280,33 @@ RPC_API int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h,
   return RPC_PORT_ERROR_NONE;
 }
 
+RPC_API int rpc_port_proxy_get_port(rpc_port_proxy_h h,
+    rpc_port_port_type_e type, rpc_port_h* port) {
+  if (h == nullptr || port == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::ProxyExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+  rpc_port_h ret_port;
+
+  switch (type) {
+    case RPC_PORT_PORT_MAIN:
+      ret_port = static_cast<rpc_port_h>(p->GetPort().get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+    case RPC_PORT_PORT_CALLBACK:
+      ret_port = static_cast<rpc_port_h>(p->GetDelegatePort().get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
 RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) {
   if (h == nullptr)
     return RPC_PORT_ERROR_INVALID_PARAMETER;
@@ -381,3 +408,31 @@ RPC_API int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h,
   p->AddReceivedEventListener(cb, user_data);
   return RPC_PORT_ERROR_NONE;
 }
+
+RPC_API int rpc_port_stub_get_port(rpc_port_stub_h h,
+    rpc_port_port_type_e type, const char *instance, rpc_port_h* port) {
+  if (h == nullptr || port == nullptr || instance == nullptr)
+    return RPC_PORT_ERROR_INVALID_PARAMETER;
+
+  auto p = static_cast<::StubExt*>(h);
+  std::lock_guard<std::recursive_mutex> lock(p->GetMutex());
+  rpc_port_h ret_port;
+
+  switch (type) {
+    case RPC_PORT_PORT_MAIN:
+      ret_port = static_cast<rpc_port_h>(p->FindPort(instance).get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+    case RPC_PORT_PORT_CALLBACK:
+      ret_port = static_cast<rpc_port_h>(p->FindDelegatePort(instance).get());
+      if (ret_port == nullptr)
+        return RPC_PORT_ERROR_IO_ERROR;
+      *port = ret_port;
+      break;
+  }
+
+  return RPC_PORT_ERROR_NONE;
+}
+
index a20d125..b866b45 100644 (file)
@@ -60,6 +60,28 @@ void Stub::SetTrusted(const bool trusted) {
   ac.SetTrusted(trusted);
 }
 
+std::shared_ptr<Port> Stub::FindPort(const std::string& instance) const {
+  for (auto& p : ports_) {
+    if (p->GetInstance() == instance && !p->IsDelegate()) {
+      return p;
+    }
+  }
+
+  return {};
+}
+
+std::shared_ptr<Port> Stub::FindDelegatePort(
+    const std::string& instance) const {
+  for (auto& p : ports_) {
+    if (p->GetInstance() == instance && p->IsDelegate()) {
+      return p;
+    }
+  }
+
+  return {};
+}
+
+
 gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond,
                               gpointer data) {
   Stub* stub = static_cast<Stub*>(data);
@@ -67,9 +89,9 @@ gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond,
   char buffer[4];
 
   for (auto& p : stub->ports_) {
-    if (p->GetFd() == fd) {
+    if (p->GetFd() == fd && !p->IsDelegate()) {
       if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
-        LOGW("Socket was disconnected from proxy");
+        LOGW("Socket was disconnected from proxy. fd(%d)", fd);
         stub->listener_->OnDisconnected(p->GetId(), p->GetInstance());
         stub->ports_.remove(p);
 
@@ -105,33 +127,37 @@ gboolean Stub::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond,
   Stub* stub = static_cast<Stub*>(data);
   int fd = g_io_channel_unix_get_fd(gio);
 
-  LOGW("Socket was disconnected");
+  LOGW("Socket was disconnected. fd(%d)", fd);
   for (auto& p : stub->ports_) {
     if (p->GetFd() == fd) {
-      stub->listener_->OnDisconnected(p->GetId(), p->GetInstance());
+      if (!p->IsDelegate()) {
+        stub->listener_->OnDisconnected(p->GetId(), p->GetInstance());
+        if (aul_rpc_port_notify_rpc_finished() != AUL_R_OK)
+          LOGW("Failed to notify rpc finished");
+      }
       stub->ports_.remove(p);
       break;
     }
   }
 
-  if (aul_rpc_port_notify_rpc_finished() != AUL_R_OK)
-    LOGW("Failed to notify rpc finished");
-
   return FALSE;
 }
 
-void Stub::OnFdReceived(const std::string& sender, int fd) {
-  ports_.emplace_back(new AcceptedPort(this, fd, sender));
+void Stub::OnFdReceived(const std::string& sender, int fds[2]) {
+  LOGW("[__OnFdReceived__] fds[0]: %d, fds[1]: %d", fds[0], fds[1]);
+  ports_.emplace_back(new AcceptedPort(this, false, fds[0], sender));
+  ports_.emplace_back(new AcceptedPort(this, true, fds[1], sender));
   for (auto& p : ports_) {
-    if (p->GetFd() == fd) {
+    if (p->GetFd() == fds[0]) {
       listener_->OnConnected(p->GetId(), p->GetInstance());
       break;
     }
   }
 }
 
-Stub::AcceptedPort::AcceptedPort(Stub* parent, int fd, const std::string& id)
-    : Port(fd, id), parent_(parent) {
+Stub::AcceptedPort::AcceptedPort(Stub* parent, bool isDelegate,
+                                 int fd, const std::string& id)
+    : Port(fd, id), parent_(parent), is_delegate_(isDelegate) {
   Watch();
 }
 
index 8883805..05ff1b2 100644 (file)
@@ -49,12 +49,17 @@ class Stub : private FdBroker::IEventListener {
   int Listen(IEventListener* ev);
   void AddPrivilege(const std::string& privilege);
   void SetTrusted(const bool trusted);
+  std::shared_ptr<Port> FindPort(const std::string& instance) const;
+  std::shared_ptr<Port> FindDelegatePort(const std::string& instance) const;
 
  private:
   class AcceptedPort : public Port {
    public:
-    AcceptedPort(Stub* parent, int fd, const std::string& id);
+    AcceptedPort(Stub* parent, bool isDelegate, int fd, const std::string& id);
     virtual ~AcceptedPort();
+    bool IsDelegate() const {
+      return is_delegate_;
+    }
 
    private:
     int Watch();
@@ -64,6 +69,7 @@ class Stub : private FdBroker::IEventListener {
     int disconn_src_ = 0;
     int src_ = 0;
     Stub* parent_;
+    bool is_delegate_ = false;
   };
 
   static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond,
@@ -71,10 +77,10 @@ class Stub : private FdBroker::IEventListener {
   static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond,
                                        gpointer data);
 
-  void OnFdReceived(const std::string& sender, int fd) override;
+  void OnFdReceived(const std::string& sender, int fds[2]) override;
 
  private:
-  std::list<std::shared_ptr<Port>> ports_;
+  std::list<std::shared_ptr<AcceptedPort>> ports_;
   IEventListener* listener_ = nullptr;
   FdBroker fd_broker_;
   std::string port_name_;
index 1057292..21e11c4 100644 (file)
@@ -242,3 +242,16 @@ TEST_F(ParcelTest, read_write) {
   ASSERT_EQ(ret, 0);
   ASSERT_TRUE(touch_from_);
 }
+
+TEST_F(ParcelTest, burst_read_write) {
+  unsigned char buf[] = { 0, 1, 2, 3, 4 };
+  int ret = rpc_port_parcel_burst_write(handle_, buf, sizeof(buf));
+  ASSERT_EQ(ret, 0);
+
+  unsigned char buf2[5] = { 0, };
+  ret = rpc_port_parcel_burst_read(handle_, buf2, sizeof(buf));
+  ASSERT_EQ(ret, 0);
+  for (int i = 0; i < 5; i++) {
+    ASSERT_EQ(buf[i], buf2[i]);
+  }
+}