/**
* @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);
/**
* @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,
* @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
* @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,
/**
* @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
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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,
/**
* @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
/**
* @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,
/**
* @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
/**
* @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,
/**
* @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
*/
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);
+
/**
* @}
*/
/**
* @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 */
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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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,
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
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;
* @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
* @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
* 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
/**
* @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
/**
* @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
/**
* @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
* @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,
* @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,
/**
* @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
/**
* @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
/**
* @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
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);
+
+/**
* @}
*/
}
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;
}
}
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;
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(),
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);
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);
}
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 {
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,
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,
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
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);
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;
}
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;
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,
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
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() {
}
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,
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
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;
+}
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;
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;
+}
+
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);
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);
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();
}
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();
int disconn_src_ = 0;
int src_ = 0;
Stub* parent_;
+ bool is_delegate_ = false;
};
static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond,
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_;
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]);
+ }
+}