summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSung-jae Park <nicesj.park@samsung.com>2014-11-23 10:37:40 +0900
committerSung-jae Park <nicesj.park@samsung.com>2014-11-23 10:57:13 +0900
commit11203dee088ed592d4c04e18a68f5ee72551aa4a (patch)
tree313ab48f67812e5af23cb132dc864711185d64ae
parentc5f0c7269cdc75f01586b6a2a5802565a8386d7d (diff)
downloadcom-core-11203dee088ed592d4c04e18a68f5ee72551aa4a.tar.gz
com-core-11203dee088ed592d4c04e18a68f5ee72551aa4a.tar.bz2
com-core-11203dee088ed592d4c04e18a68f5ee72551aa4a.zip
Add new method for sending/receving file descriptors
between local processes. [model] Redwood,Kiran,B3(Wearable) [binary_type] AP [customer] Docomo/Orange/ATT/Open [issue#] N/A [problem] [cause] [solution] [team] HomeTF [request] [horizontal_expansion] Change-Id: Ifbcbae54f95c176bf585d3be2f6266460bd27434
-rw-r--r--include/com-core.h28
-rw-r--r--include/com-core_thread.h3
-rw-r--r--include/secure_socket.h10
-rw-r--r--packaging/libcom-core.spec2
-rw-r--r--src/com-core.c1030
-rw-r--r--src/com-core_packet.c1078
-rw-r--r--src/com-core_thread.c1385
-rw-r--r--src/secure_socket.c785
8 files changed, 2217 insertions, 2104 deletions
diff --git a/include/com-core.h b/include/com-core.h
index 0631a71..16d743c 100644
--- a/include/com-core.h
+++ b/include/com-core.h
@@ -133,6 +133,34 @@ extern int com_core_recv(int handle, char *buffer, int size, int *sender_pid, do
*/
extern int com_core_send(int handle, const char *buffer, int size, double timeout);
+/**
+ * @brief
+ * @details
+ * @remarks
+ * @param[in] handle
+ * @param[in] buffer
+ * @param[in] size
+ * @param[in] timeout
+ * @param[in] fd
+ * @return int
+ * @retval
+ * @sa
+ */
+extern int com_core_send_with_fd(int handle, const char *buffer, int size, double timeout, int fd);
+
+/**
+ * @brief
+ * @details
+ * @remarks
+ * @param[in] handle
+ * @param[out] buffer
+ * @param[in] size
+ * @param[out] sender_pid
+ * @param[in] timeout
+ * @param[out] fd
+ */
+extern int com_core_recv_with_fd(int handle, char *buffer, int size, int *sender_pid, double timeout, int *fd);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/com-core_thread.h b/include/com-core_thread.h
index 9e28314..a2463a2 100644
--- a/include/com-core_thread.h
+++ b/include/com-core_thread.h
@@ -31,6 +31,9 @@ extern int com_core_thread_client_destroy(int handle);
extern int com_core_thread_recv(int handle, char *buffer, int size, int *sender_pid, double timeout);
extern int com_core_thread_send(int handle, const char *buffer, int size, double timeout);
+extern int com_core_thread_recv_with_fd(int handle, char *buffer, int size, int *sender_pid, double timeout, int *fd);
+extern int com_core_thread_send_with_fd(int handle, const char *buffer, int size, double timeout, int fd);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/secure_socket.h b/include/secure_socket.h
index b53e52c..8c9d76b 100644
--- a/include/secure_socket.h
+++ b/include/secure_socket.h
@@ -81,25 +81,27 @@ extern int secure_socket_get_connection_handle(int server_handle);
* \param[in] conn
* \param[in] buffer
* \param[in] size
+ * \param[in] fd Shared fd which will be used from receiver process.
* \return int
* \retval
* \sa
*/
-extern int secure_socket_send(int conn, const char *buffer, int size);
+extern int secure_socket_send(int conn, const char *buffer, int size, int fd);
/*!
* \brief Recv data from the connected peer. and its PID value
* \details N/A
* \remarks N/A
* \param[in] connn
- * \param[in] buffer
+ * \param[out] buffer
* \param[in] size
- * \param[in] sender_pid
+ * \param[out] sender_pid
+ * \param[out] fd shared fd which is comes from sender process.
* \return int
* \retval
* \sa
*/
-extern int secure_socket_recv(int conn, char *buffer, int size, int *sender_pid);
+extern int secure_socket_recv(int conn, char *buffer, int size, int *sender_pid, int *fd);
/*!
* \brief Destroy a connection
diff --git a/packaging/libcom-core.spec b/packaging/libcom-core.spec
index ebd5bd5..e20f156 100644
--- a/packaging/libcom-core.spec
+++ b/packaging/libcom-core.spec
@@ -1,6 +1,6 @@
Name: libcom-core
Summary: Library for the light-weight IPC
-Version: 0.6.0
+Version: 0.7.0
Release: 1
Group: Base/IPC
License: Apache-2.0
diff --git a/src/com-core.c b/src/com-core.c
index f1973f7..bf627e6 100644
--- a/src/com-core.c
+++ b/src/com-core.c
@@ -37,643 +37,657 @@
#include "util.h"
static struct {
- struct dlist *watch_list;
- struct dlist *conn_cb_list;
- struct dlist *disconn_cb_list;
- enum processing_event_callback {
- PROCESSING_NONE = 0x0,
- PROCESSING_DISCONNECTION = 0x01,
- PROCESSING_CONNECTION = 0x02,
- } processing_event_callback;
+ struct dlist *watch_list;
+ struct dlist *conn_cb_list;
+ struct dlist *disconn_cb_list;
+ enum processing_event_callback {
+ PROCESSING_NONE = 0x0,
+ PROCESSING_DISCONNECTION = 0x01,
+ PROCESSING_CONNECTION = 0x02,
+ } processing_event_callback;
} s_info = {
- .watch_list = NULL,
- .conn_cb_list = NULL,
- .disconn_cb_list = NULL,
- .processing_event_callback = PROCESSING_NONE,
+ .watch_list = NULL,
+ .conn_cb_list = NULL,
+ .disconn_cb_list = NULL,
+ .processing_event_callback = PROCESSING_NONE,
};
struct watch_item {
- int server_fd;
- int fd;
- guint id;
- void *cbdata;
+ int server_fd;
+ int fd;
+ guint id;
+ void *cbdata;
};
struct cbdata {
- int (*service_cb)(int fd, void *data);
- void *data;
+ int (*service_cb)(int fd, void *data);
+ void *data;
};
struct evtdata {
- int deleted;
- int (*evt_cb)(int fd, void *data);
- void *data;
+ int deleted;
+ int (*evt_cb)(int fd, void *data);
+ void *data;
};
static int watch_item_create(int server_fd, int handle, guint id, void *cbdata)
{
- struct watch_item *item;
+ struct watch_item *item;
- item = malloc(sizeof(*item));
- if (!item) {
- return -ENOMEM;
- }
+ item = malloc(sizeof(*item));
+ if (!item) {
+ return -ENOMEM;
+ }
- item->server_fd = server_fd;
- item->fd = handle;
- item->id = id;
- item->cbdata = cbdata;
+ item->server_fd = server_fd;
+ item->fd = handle;
+ item->id = id;
+ item->cbdata = cbdata;
- DbgPrint("Watch Item is created for %d/%d\n", server_fd, handle);
- s_info.watch_list = dlist_append(s_info.watch_list, item);
- return 0;
+ DbgPrint("Watch Item is created for %d/%d\n", server_fd, handle);
+ s_info.watch_list = dlist_append(s_info.watch_list, item);
+ return 0;
}
static int watch_item_destroy(int handle, int remove_id, int remove_cbdata)
{
- struct dlist *l;
- struct dlist *n;
- struct watch_item *item;
+ struct dlist *l;
+ struct dlist *n;
+ struct watch_item *item;
- dlist_foreach_safe(s_info.watch_list, l, n, item) {
- if (item->fd == handle) {
- s_info.watch_list = dlist_remove(s_info.watch_list, l);
+ dlist_foreach_safe(s_info.watch_list, l, n, item) {
+ if (item->fd == handle) {
+ s_info.watch_list = dlist_remove(s_info.watch_list, l);
- DbgPrint("Watch item is destroyed for %d/%d\n", item->server_fd, item->fd);
+ DbgPrint("Watch item is destroyed for %d/%d\n", item->server_fd, item->fd);
- if (remove_id && item->id) {
- g_source_remove(item->id);
- }
+ if (remove_id && item->id) {
+ g_source_remove(item->id);
+ }
- if (remove_cbdata && item->cbdata) {
- free(item->cbdata);
- }
+ if (remove_cbdata && item->cbdata) {
+ free(item->cbdata);
+ }
- free(item);
- return 0;
- }
+ free(item);
+ return 0;
}
+ }
- DbgPrint("No entry found\n");
- return -ENOENT;
+ DbgPrint("No entry found\n");
+ return -ENOENT;
}
static void watch_item_destroy_all(int socket_fd)
{
- struct dlist *l;
- struct dlist *n;
- struct watch_item *item;
-
- dlist_foreach_safe(s_info.watch_list, l, n, item) {
- if (item->server_fd == socket_fd) {
- DbgPrint("Watch item removed: %d/%d\n", item->server_fd, item->fd);
- /*!
- * \WARN
- * If the watch_list item is removed from disconnected
- * callback, this list loop can be broken.
- * Please check it again.
- */
- invoke_disconn_cb_list(item->fd, 0, 0, 0);
-
- s_info.watch_list = dlist_remove(s_info.watch_list, l);
- if (item->id > 0) {
- g_source_remove(item->id);
- }
- free(item->cbdata);
- free(item);
- }
- }
+ struct dlist *l;
+ struct dlist *n;
+ struct watch_item *item;
+
+ dlist_foreach_safe(s_info.watch_list, l, n, item) {
+ if (item->server_fd == socket_fd) {
+ DbgPrint("Watch item removed: %d/%d\n", item->server_fd, item->fd);
+ /*!
+ * \WARN
+ * If the watch_list item is removed from disconnected
+ * callback, this list loop can be broken.
+ * Please check it again.
+ */
+ invoke_disconn_cb_list(item->fd, 0, 0, 0);
+
+ s_info.watch_list = dlist_remove(s_info.watch_list, l);
+ if (item->id > 0) {
+ g_source_remove(item->id);
+ }
+ free(item->cbdata);
+ free(item);
+ }
+ }
}
HAPI void invoke_con_cb_list(int server_fd, int handle, guint id, void *data, int watch)
{
- struct dlist *l;
- struct dlist *n;
- struct evtdata *cbdata;
-
- if (watch) {
- if (watch_item_create(server_fd, handle, id, data) < 0) {
- ErrPrint("Failed to create a watch item\n");
- }
- }
-
- s_info.processing_event_callback |= PROCESSING_CONNECTION;
- dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
- /*!
- * \NOTE
- * cbdata->deleted must has to be checked before call the function and
- * return from the function call.
- */
- if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
- s_info.conn_cb_list = dlist_remove(s_info.conn_cb_list, l);
- free(cbdata);
- }
- }
- s_info.processing_event_callback &= ~PROCESSING_CONNECTION;
+ struct dlist *l;
+ struct dlist *n;
+ struct evtdata *cbdata;
+
+ if (watch) {
+ if (watch_item_create(server_fd, handle, id, data) < 0) {
+ ErrPrint("Failed to create a watch item\n");
+ }
+ }
+
+ s_info.processing_event_callback |= PROCESSING_CONNECTION;
+ dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
+ /*!
+ * \NOTE
+ * cbdata->deleted must has to be checked before call the function and
+ * return from the function call.
+ */
+ if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
+ s_info.conn_cb_list = dlist_remove(s_info.conn_cb_list, l);
+ free(cbdata);
+ }
+ }
+ s_info.processing_event_callback &= ~PROCESSING_CONNECTION;
}
HAPI void invoke_disconn_cb_list(int handle, int remove_id, int remove_data, int watch)
{
- struct dlist *l;
- struct dlist *n;
- struct evtdata *cbdata;
-
- s_info.processing_event_callback |= PROCESSING_DISCONNECTION;
- dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
- /*!
- * \NOTE
- * cbdata->deleted must has to be checked before call the function and
- * return from the function call.
- */
- if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
- s_info.disconn_cb_list = dlist_remove(s_info.disconn_cb_list, l);
- free(cbdata);
- }
- }
- s_info.processing_event_callback &= ~PROCESSING_DISCONNECTION;
-
- if (watch) {
- if (watch_item_destroy(handle, remove_id, remove_data) < 0) {
- ErrPrint("Failed to destroy watch item\n");
- }
- }
+ struct dlist *l;
+ struct dlist *n;
+ struct evtdata *cbdata;
+
+ s_info.processing_event_callback |= PROCESSING_DISCONNECTION;
+ dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
+ /*!
+ * \NOTE
+ * cbdata->deleted must has to be checked before call the function and
+ * return from the function call.
+ */
+ if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
+ s_info.disconn_cb_list = dlist_remove(s_info.disconn_cb_list, l);
+ free(cbdata);
+ }
+ }
+ s_info.processing_event_callback &= ~PROCESSING_DISCONNECTION;
+
+ if (watch) {
+ if (watch_item_destroy(handle, remove_id, remove_data) < 0) {
+ ErrPrint("Failed to destroy watch item\n");
+ }
+ }
}
static int validate_handle(int fd)
{
- int error;
- socklen_t len;
+ int error;
+ socklen_t len;
- len = sizeof(error);
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
- ErrPrint("getsockopt: %s\n", strerror(errno));
- return 0;
- }
+ len = sizeof(error);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+ ErrPrint("getsockopt: %s\n", strerror(errno));
+ return 0;
+ }
- return !(error == EBADF);
+ return !(error == EBADF);
}
static gboolean client_cb(GIOChannel *src, GIOCondition cond, gpointer data)
{
- int client_fd;
- struct cbdata *cbdata = data;
- int ret;
-
- client_fd = g_io_channel_unix_get_fd(src);
-
- if (!(cond & G_IO_IN)) {
- DbgPrint("Client is disconencted\n");
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
- secure_socket_destroy_handle(client_fd);
- return FALSE;
- }
-
- if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
- DbgPrint("Client connection is lost\n");
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
- secure_socket_destroy_handle(client_fd);
- return FALSE;
- }
-
- ret = cbdata->service_cb(client_fd, cbdata->data);
- if (ret < 0) {
- DbgPrint("service callback returns %d < 0\n", ret);
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
- secure_socket_destroy_handle(client_fd);
- return FALSE;
- }
-
- /* Check whether the socket FD is closed or not */
- if (!validate_handle(client_fd)) {
- invoke_disconn_cb_list(client_fd, 0, 1, 1);
- secure_socket_destroy_handle(client_fd);
- return FALSE;
- }
-
- return TRUE;
+ int client_fd;
+ struct cbdata *cbdata = data;
+ int ret;
+
+ client_fd = g_io_channel_unix_get_fd(src);
+
+ if (!(cond & G_IO_IN)) {
+ DbgPrint("Client is disconencted\n");
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ secure_socket_destroy_handle(client_fd);
+ return FALSE;
+ }
+
+ if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+ DbgPrint("Client connection is lost\n");
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ secure_socket_destroy_handle(client_fd);
+ return FALSE;
+ }
+
+ ret = cbdata->service_cb(client_fd, cbdata->data);
+ if (ret < 0) {
+ DbgPrint("service callback returns %d < 0\n", ret);
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ secure_socket_destroy_handle(client_fd);
+ return FALSE;
+ }
+
+ /* Check whether the socket FD is closed or not */
+ if (!validate_handle(client_fd)) {
+ invoke_disconn_cb_list(client_fd, 0, 1, 1);
+ secure_socket_destroy_handle(client_fd);
+ return FALSE;
+ }
+
+ return TRUE;
}
static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer cbdata)
{
- int socket_fd;
- int client_fd;
- GIOChannel *gio;
- guint id;
-
- socket_fd = g_io_channel_unix_get_fd(src);
- if (!(cond & G_IO_IN)) {
- ErrPrint("Accept socket closed\n");
- watch_item_destroy_all(socket_fd);
- secure_socket_destroy_handle(socket_fd);
- free(cbdata);
- return FALSE;
- }
-
- if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
- ErrPrint("Client connection is lost\n");
- watch_item_destroy_all(socket_fd);
- secure_socket_destroy_handle(socket_fd);
- free(cbdata);
- return FALSE;
- }
-
- client_fd = secure_socket_get_connection_handle(socket_fd);
- if (client_fd < 0) {
- /* Keep server running */
- return TRUE;
- }
- DbgPrint("New connectino arrived: server(%d), client(%d)\n", socket_fd, client_fd);
+ int socket_fd;
+ int client_fd;
+ GIOChannel *gio;
+ guint id;
+
+ socket_fd = g_io_channel_unix_get_fd(src);
+ if (!(cond & G_IO_IN)) {
+ ErrPrint("Accept socket closed\n");
+ watch_item_destroy_all(socket_fd);
+ secure_socket_destroy_handle(socket_fd);
+ free(cbdata);
+ return FALSE;
+ }
+
+ if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+ ErrPrint("Client connection is lost\n");
+ watch_item_destroy_all(socket_fd);
+ secure_socket_destroy_handle(socket_fd);
+ free(cbdata);
+ return FALSE;
+ }
+
+ client_fd = secure_socket_get_connection_handle(socket_fd);
+ if (client_fd < 0) {
+ /* Keep server running */
+ return TRUE;
+ }
+ DbgPrint("New connectino arrived: server(%d), client(%d)\n", socket_fd, client_fd);
- if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
+ if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
- if (fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
+ if (fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
- gio = g_io_channel_unix_new(client_fd);
- if (!gio) {
- ErrPrint("Failed to get gio\n");
- secure_socket_destroy_handle(client_fd);
- /* Keep server running */
- return TRUE;
- }
+ gio = g_io_channel_unix_new(client_fd);
+ if (!gio) {
+ ErrPrint("Failed to get gio\n");
+ secure_socket_destroy_handle(client_fd);
+ /* Keep server running */
+ return TRUE;
+ }
- g_io_channel_set_close_on_unref(gio, FALSE);
+ g_io_channel_set_close_on_unref(gio, FALSE);
- id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)client_cb, cbdata);
- if (id <= 0) {
- GError *err = NULL;
+ id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)client_cb, cbdata);
+ if (id <= 0) {
+ GError *err = NULL;
- ErrPrint("Failed to add IO watch\n");
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(client_fd);
- /* Keep server running */
- return TRUE;
+ ErrPrint("Failed to add IO watch\n");
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
-
g_io_channel_unref(gio);
-
- invoke_con_cb_list(socket_fd, client_fd, id, NULL, 1);
-
- if (!validate_handle(socket_fd)) {
- watch_item_destroy_all(socket_fd);
- return FALSE;
- }
-
+ secure_socket_destroy_handle(client_fd);
/* Keep server running */
return TRUE;
-}
-
-EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
-{
- GIOChannel *gio;
- guint id;
- int fd;
- struct cbdata *cbdata;
-
- cbdata = malloc(sizeof(*cbdata));
- if (!cbdata) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return -ENOMEM;
- }
-
- cbdata->service_cb = service_cb;
- cbdata->data = data;
+ }
- fd = secure_socket_create_server(addr);
- if (fd < 0) {
- free(cbdata);
- return fd;
- }
+ g_io_channel_unref(gio);
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
+ invoke_con_cb_list(socket_fd, client_fd, id, NULL, 1);
- if (!is_sync && fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
+ if (!validate_handle(socket_fd)) {
+ watch_item_destroy_all(socket_fd);
+ return FALSE;
+ }
- DbgPrint("Create new IO channel for server FD: %d\n", fd);
- gio = g_io_channel_unix_new(fd);
- if (!gio) {
- ErrPrint("Failed to create new io channel\n");
- free(cbdata);
- secure_socket_destroy_handle(fd);
- return -EIO;
- }
+ /* Keep server running */
+ return TRUE;
+}
- g_io_channel_set_close_on_unref(gio, FALSE);
-
- id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc)accept_cb, cbdata);
- if (id <= 0) {
- GError *err = NULL;
- ErrPrint("Failed to add IO watch\n");
- free(cbdata);
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(fd);
- return -EIO;
+EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
+{
+ GIOChannel *gio;
+ guint id;
+ int fd;
+ struct cbdata *cbdata;
+
+ cbdata = malloc(sizeof(*cbdata));
+ if (!cbdata) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ cbdata->service_cb = service_cb;
+ cbdata->data = data;
+
+ fd = secure_socket_create_server(addr);
+ if (fd < 0) {
+ free(cbdata);
+ return fd;
+ }
+
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("fcntl: %s\n", strerror(errno));
+ }
+
+ if (!is_sync && fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("fcntl: %s\n", strerror(errno));
+ }
+
+ DbgPrint("Create new IO channel for server FD: %d\n", fd);
+ gio = g_io_channel_unix_new(fd);
+ if (!gio) {
+ ErrPrint("Failed to create new io channel\n");
+ free(cbdata);
+ secure_socket_destroy_handle(fd);
+ return -EIO;
+ }
+
+ g_io_channel_set_close_on_unref(gio, FALSE);
+
+ id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc)accept_cb, cbdata);
+ if (id <= 0) {
+ GError *err = NULL;
+ ErrPrint("Failed to add IO watch\n");
+ free(cbdata);
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
+ g_io_channel_unref(gio);
+ secure_socket_destroy_handle(fd);
+ return -EIO;
+ }
- if (watch_item_create(fd, fd, id, cbdata) < 0) {
- GError *err = NULL;
+ if (watch_item_create(fd, fd, id, cbdata) < 0) {
+ GError *err = NULL;
- ErrPrint("Failed to create a watch item\n");
- g_source_remove(id);
+ ErrPrint("Failed to create a watch item\n");
+ g_source_remove(id);
- free(cbdata);
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(fd);
- return -ENOMEM;
+ free(cbdata);
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
-
g_io_channel_unref(gio);
- return fd;
+ secure_socket_destroy_handle(fd);
+ return -ENOMEM;
+ }
+
+ g_io_channel_unref(gio);
+ return fd;
}
EAPI int com_core_client_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
{
- GIOChannel *gio;
- guint id;
- int client_fd;
- struct cbdata *cbdata;
-
- cbdata = malloc(sizeof(*cbdata));
- if (!cbdata) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return -ENOMEM;
+ GIOChannel *gio;
+ guint id;
+ int client_fd;
+ struct cbdata *cbdata;
+
+ cbdata = malloc(sizeof(*cbdata));
+ if (!cbdata) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ cbdata->service_cb = service_cb;
+ cbdata->data = data;
+
+ client_fd = secure_socket_create_client(addr);
+ if (client_fd < 0) {
+ free(cbdata);
+ return client_fd;
+ }
+
+ if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+
+ if (!is_sync && fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+
+ gio = g_io_channel_unix_new(client_fd);
+ if (!gio) {
+ ErrPrint("Failed to create a new IO channel\n");
+ free(cbdata);
+ secure_socket_destroy_handle(client_fd);
+ return -EIO;
+ }
+
+ g_io_channel_set_close_on_unref(gio, FALSE);
+
+ id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)client_cb, cbdata);
+ if (id <= 0) {
+ GError *err = NULL;
+ ErrPrint("Failed to add IO watch\n");
+ free(cbdata);
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
+ g_io_channel_unref(gio);
+ secure_socket_destroy_handle(client_fd);
+ return -EIO;
+ }
- cbdata->service_cb = service_cb;
- cbdata->data = data;
+ g_io_channel_unref(gio);
- client_fd = secure_socket_create_client(addr);
- if (client_fd < 0) {
- free(cbdata);
- return client_fd;
- }
+ invoke_con_cb_list(client_fd, client_fd, id, cbdata, 1);
+ return client_fd;
+}
- if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
+EAPI int com_core_add_event_callback(enum com_core_event_type type, int (*evt_cb)(int handle, void *data), void *data)
+{
+ struct evtdata *cbdata;
+ cbdata = malloc(sizeof(*cbdata));
+ if (!cbdata) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ cbdata->evt_cb = evt_cb;
+ cbdata->data = data;
+ cbdata->deleted = 0;
+
+ if (type == CONNECTOR_CONNECTED) {
+ s_info.conn_cb_list = dlist_append(s_info.conn_cb_list, cbdata);
+ } else {
+ s_info.disconn_cb_list = dlist_append(s_info.disconn_cb_list, cbdata);
+ }
+ return 0;
+}
- if (!is_sync && fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
+EAPI int com_core_recv_with_fd(int handle, char *buffer, int size, int *sender_pid, double timeout, int *fd)
+{
+ int readsize;
+ int ret;
+ int *recv_fd;
+
+ fd_set set;
+
+ recv_fd = fd;
+ readsize = 0;
+ while (size > 0) {
+ FD_ZERO(&set);
+ FD_SET(handle, &set);
+
+ if (timeout > 0.0f) {
+ struct timeval tv;
+
+ tv.tv_sec = (unsigned long)timeout;
+ tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
+ ret = select(handle + 1, &set, NULL, NULL, &tv);
+ } else if (timeout == 0.0f) {
+ ret = select(handle + 1, &set, NULL, NULL, NULL);
+ } else {
+ ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
+ return -EINVAL;
}
- gio = g_io_channel_unix_new(client_fd);
- if (!gio) {
- ErrPrint("Failed to create a new IO channel\n");
- free(cbdata);
- secure_socket_destroy_handle(client_fd);
- return -EIO;
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EINTR) {
+ DbgPrint("Select receives INTR\n");
+ continue;
+ }
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ ErrPrint("Timeout expired\n");
+ break;
}
- g_io_channel_set_close_on_unref(gio, FALSE);
-
- id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)client_cb, cbdata);
- if (id <= 0) {
- GError *err = NULL;
- ErrPrint("Failed to add IO watch\n");
- free(cbdata);
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(client_fd);
- return -EIO;
+ if (!FD_ISSET(handle, &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ return -EINVAL;
}
- g_io_channel_unref(gio);
-
- invoke_con_cb_list(client_fd, client_fd, id, cbdata, 1);
- return client_fd;
+ ret = secure_socket_recv(handle, buffer + readsize, size, sender_pid, recv_fd);
+ if (ret < 0) {
+ if (ret == -EAGAIN) {
+ DbgPrint("Retry to get data (%d:%d)\n", readsize, size);
+ continue;
+ }
+ DbgPrint("[%d] recv returns: %d\n", handle, ret);
+ return ret;
+ } else if (ret == 0) {
+ DbgPrint("Disconnected(req.size: %d)\n", size);
+ return 0;
+ }
+
+ recv_fd = NULL; /** Get it only for the first time */
+ size -= ret;
+ readsize += ret;
+ }
+
+ return readsize;
}
-EAPI int com_core_add_event_callback(enum com_core_event_type type, int (*evt_cb)(int handle, void *data), void *data)
+EAPI int com_core_recv(int handle, char *buffer, int size, int *sender_pid, double timeout)
{
- struct evtdata *cbdata;
- cbdata = malloc(sizeof(*cbdata));
- if (!cbdata) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return -ENOMEM;
- }
-
- cbdata->evt_cb = evt_cb;
- cbdata->data = data;
- cbdata->deleted = 0;
-
- if (type == CONNECTOR_CONNECTED) {
- s_info.conn_cb_list = dlist_append(s_info.conn_cb_list, cbdata);
- } else {
- s_info.disconn_cb_list = dlist_append(s_info.disconn_cb_list, cbdata);
- }
- return 0;
+ return com_core_recv_with_fd(handle, buffer, size, sender_pid, timeout, NULL);
}
-EAPI int com_core_recv(int handle, char *buffer, int size, int *sender_pid, double timeout)
+EAPI int com_core_send_with_fd(int handle, const char *buffer, int size, double timeout, int fd)
{
- int readsize;
- int ret;
+ int writesize;
+ int ret;
- fd_set set;
+ fd_set set;
- readsize = 0;
- while (size > 0) {
- FD_ZERO(&set);
- FD_SET(handle, &set);
+ writesize = 0;
+ while (size > 0) {
- if (timeout > 0.0f) {
- struct timeval tv;
+ FD_ZERO(&set);
+ FD_SET(handle, &set);
- tv.tv_sec = (unsigned long)timeout;
- tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
- ret = select(handle + 1, &set, NULL, NULL, &tv);
- } else if (timeout == 0.0f) {
- ret = select(handle + 1, &set, NULL, NULL, NULL);
- } else {
- ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
- return -EINVAL;
- }
+ if (timeout > 0.0f) {
+ struct timeval tv;
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- DbgPrint("Select receives INTR\n");
- continue;
- }
- ErrPrint("Error: %s\n", strerror(errno));
- return ret;
- } else if (ret == 0) {
- ErrPrint("Timeout expired\n");
- break;
- }
+ tv.tv_sec = (unsigned long)timeout;
+ tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
- if (!FD_ISSET(handle, &set)) {
- ErrPrint("Unexpected handle is toggled\n");
- return -EINVAL;
- }
+ ret = select(handle + 1, NULL, &set, NULL, &tv);
+ } else if (timeout == 0.0f) {
+ ret = select(handle + 1, NULL, &set, NULL, NULL);
+ } else {
+ ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
+ return -EINVAL;
+ }
- ret = secure_socket_recv(handle, buffer + readsize, size, sender_pid);
- if (ret < 0) {
- if (ret == -EAGAIN) {
- DbgPrint("Retry to get data (%d:%d)\n", readsize, size);
- continue;
- }
- DbgPrint("[%d] recv returns: %d\n", handle, ret);
- return ret;
- } else if (ret == 0) {
- DbgPrint("Disconnected(req.size: %d)\n", size);
- return 0;
- }
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EINTR) {
+ DbgPrint("Select receives INTR\n");
+ continue;
+ }
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ ErrPrint("Timeout expired\n");
+ break;
+ }
- size -= ret;
- readsize += ret;
+ if (!FD_ISSET(handle, &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ return -EINVAL;
}
- return readsize;
+ ret = secure_socket_send(handle, buffer + writesize, size, fd);
+ if (ret < 0) {
+ if (ret == -EAGAIN) {
+ DbgPrint("Retry to send data (%d:%d)\n", writesize, size);
+ continue;
+ }
+ DbgPrint("Failed to send: %d\n", ret);
+ return ret;
+ } else if (ret == 0) {
+ DbgPrint("Disconnected? : Send bytes: 0\n");
+ return 0;
+ }
+
+ fd = -1; /** Send only once if it is fd */
+ size -= ret;
+ writesize += ret;
+ }
+
+ return writesize;
}
EAPI int com_core_send(int handle, const char *buffer, int size, double timeout)
{
- int writesize;
- int ret;
-
- fd_set set;
-
- writesize = 0;
- while (size > 0) {
-
- FD_ZERO(&set);
- FD_SET(handle, &set);
+ return com_core_send_with_fd(handle, buffer, size, timeout, -1);
+}
- if (timeout > 0.0f) {
- struct timeval tv;
+EAPI void *com_core_del_event_callback(enum com_core_event_type type, int (*cb)(int handle, void *data), void *data)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct evtdata *cbdata;
- tv.tv_sec = (unsigned long)timeout;
- tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
+ if (type == CONNECTOR_CONNECTED) {
+ dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
+ if (cbdata->evt_cb == cb && cbdata->data == data) {
+ void *data;
+ data = cbdata->data;
- ret = select(handle + 1, NULL, &set, NULL, &tv);
- } else if (timeout == 0.0f) {
- ret = select(handle + 1, NULL, &set, NULL, NULL);
+ if ((s_info.processing_event_callback & PROCESSING_CONNECTION) == PROCESSING_CONNECTION) {
+ cbdata->deleted = 1;
} else {
- ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
- return -EINVAL;
+ dlist_remove_data(s_info.conn_cb_list, cbdata);
+ free(cbdata);
}
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- DbgPrint("Select receives INTR\n");
- continue;
- }
- ErrPrint("Error: %s\n", strerror(errno));
- return ret;
- } else if (ret == 0) {
- ErrPrint("Timeout expired\n");
- break;
- }
-
- if (!FD_ISSET(handle, &set)) {
- ErrPrint("Unexpected handle is toggled\n");
- return -EINVAL;
- }
-
- ret = secure_socket_send(handle, buffer + writesize, size);
- if (ret < 0) {
- if (ret == -EAGAIN) {
- DbgPrint("Retry to send data (%d:%d)\n", writesize, size);
- continue;
- }
- DbgPrint("Failed to send: %d\n", ret);
- return ret;
- } else if (ret == 0) {
- DbgPrint("Disconnected? : Send bytes: 0\n");
- return 0;
- }
-
- size -= ret;
- writesize += ret;
+ return data;
+ }
}
+ } else {
+ dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
+ if (cbdata->evt_cb == cb && cbdata->data == data) {
+ void *data;
+ data = cbdata->data;
- return writesize;
-}
-
-EAPI void *com_core_del_event_callback(enum com_core_event_type type, int (*cb)(int handle, void *data), void *data)
-{
- struct dlist *l;
- struct dlist *n;
- struct evtdata *cbdata;
-
- if (type == CONNECTOR_CONNECTED) {
- dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
- if (cbdata->evt_cb == cb && cbdata->data == data) {
- void *data;
- data = cbdata->data;
-
- if ((s_info.processing_event_callback & PROCESSING_CONNECTION) == PROCESSING_CONNECTION) {
- cbdata->deleted = 1;
- } else {
- dlist_remove_data(s_info.conn_cb_list, cbdata);
- free(cbdata);
- }
-
- return data;
- }
- }
- } else {
- dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
- if (cbdata->evt_cb == cb && cbdata->data == data) {
- void *data;
- data = cbdata->data;
-
- if ((s_info.processing_event_callback & PROCESSING_DISCONNECTION) == PROCESSING_DISCONNECTION) {
- cbdata->deleted = 1;
- } else {
- dlist_remove_data(s_info.disconn_cb_list, cbdata);
- free(cbdata);
- }
- return data;
- }
+ if ((s_info.processing_event_callback & PROCESSING_DISCONNECTION) == PROCESSING_DISCONNECTION) {
+ cbdata->deleted = 1;
+ } else {
+ dlist_remove_data(s_info.disconn_cb_list, cbdata);
+ free(cbdata);
}
+ return data;
+ }
}
+ }
- return NULL;
+ return NULL;
}
EAPI int com_core_server_destroy(int handle)
{
- DbgPrint("Close server handle[%d]\n", handle);
- invoke_disconn_cb_list(handle, 1, 1, 1);
- secure_socket_destroy_handle(handle);
- return 0;
+ DbgPrint("Close server handle[%d]\n", handle);
+ invoke_disconn_cb_list(handle, 1, 1, 1);
+ secure_socket_destroy_handle(handle);
+ return 0;
}
EAPI int com_core_client_destroy(int handle)
{
- DbgPrint("Close client handle[%d]\n", handle);
- invoke_disconn_cb_list(handle, 1, 1, 1);
- secure_socket_destroy_handle(handle);
- return 0;
+ DbgPrint("Close client handle[%d]\n", handle);
+ invoke_disconn_cb_list(handle, 1, 1, 1);
+ secure_socket_destroy_handle(handle);
+ return 0;
}
/* End of a file */
diff --git a/src/com-core_packet.c b/src/com-core_packet.c
index 1f4169d..ea9ffc6 100644
--- a/src/com-core_packet.c
+++ b/src/com-core_packet.c
@@ -44,706 +44,720 @@
*/
static struct info {
- struct dlist *recv_list;
- struct dlist *request_list;
- char *addr;
+ struct dlist *recv_list;
+ struct dlist *request_list;
+ char *addr;
- struct {
- int (*server_create)(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data);
- int (*client_create)(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data);
- int (*server_destroy)(int handle);
- int (*client_destroy)(int handle);
+ struct {
+ int (*server_create)(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data);
+ int (*client_create)(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data);
+ int (*server_destroy)(int handle);
+ int (*client_destroy)(int handle);
- int (*recv)(int handle, char *buffer, int size, int *sender_pid, double timeout);
- int (*send)(int handle, const char *buffer, int size, double timeout);
- } vtable;
+ int (*recv)(int handle, char *buffer, int size, int *sender_pid, double timeout);
+ int (*send)(int handle, const char *buffer, int size, double timeout);
- int initialized;
+ int (*recv_with_fd)(int handle, char *buffer, int size, int *sender_pid, double timeout, int *fd);
+ int (*send_with_fd)(int handle, const char *buffer, int size, double timeout, int fd);
+ } vtable;
+
+ int initialized;
} s_info = {
- .recv_list = NULL,
- .request_list = NULL,
- .addr = NULL,
- .vtable = {
- .server_create = com_core_server_create,
- .client_create = com_core_client_create,
- .server_destroy = com_core_server_destroy,
- .client_destroy = com_core_client_destroy,
- .recv = com_core_recv,
- .send = com_core_send,
- },
- .initialized = 0,
+ .recv_list = NULL,
+ .request_list = NULL,
+ .addr = NULL,
+ .vtable = {
+ .server_create = com_core_server_create,
+ .client_create = com_core_client_create,
+ .server_destroy = com_core_server_destroy,
+ .client_destroy = com_core_client_destroy,
+ .recv = com_core_recv,
+ .send = com_core_send,
+ .recv_with_fd = com_core_recv_with_fd,
+ .send_with_fd = com_core_send_with_fd,
+ },
+ .initialized = 0,
};
struct request_ctx {
- pid_t pid;
- int handle;
+ pid_t pid;
+ int handle;
- struct packet *packet;
- int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data);
- void *data;
+ struct packet *packet;
+ int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data);
+ void *data;
- int inuse;
+ int inuse;
};
struct recv_ctx {
- enum {
- RECV_STATE_INIT,
- RECV_STATE_HEADER,
- RECV_STATE_BODY,
- RECV_STATE_READY
- } state;
- int handle;
- int offset;
- pid_t pid;
- struct packet *packet;
- double timeout;
-
- int inuse;
+ enum {
+ RECV_STATE_INIT,
+ RECV_STATE_HEADER,
+ RECV_STATE_BODY,
+ RECV_STATE_READY
+ } state;
+ int handle;
+ int offset;
+ pid_t pid;
+ struct packet *packet;
+ double timeout;
+
+ int inuse;
};
static inline struct request_ctx *find_request_ctx(int handle, double seq)
{
- struct request_ctx *ctx;
- struct dlist *l;
+ struct request_ctx *ctx;
+ struct dlist *l;
- dlist_foreach(s_info.request_list, l, ctx) {
- if (ctx->handle == handle && packet_seq(ctx->packet) == seq) {
- return ctx;
- }
+ dlist_foreach(s_info.request_list, l, ctx) {
+ if (ctx->handle == handle && packet_seq(ctx->packet) == seq) {
+ return ctx;
}
+ }
- return NULL;
+ return NULL;
}
static inline void destroy_request_ctx(struct request_ctx *ctx)
{
- struct dlist *l;
+ struct dlist *l;
- if (ctx->inuse) {
- return;
- }
+ if (ctx->inuse) {
+ return;
+ }
- l = dlist_find_data(s_info.request_list, ctx);
- if (!l) {
- return;
- }
+ l = dlist_find_data(s_info.request_list, ctx);
+ if (!l) {
+ return;
+ }
- s_info.request_list = dlist_remove(s_info.request_list, l);
+ s_info.request_list = dlist_remove(s_info.request_list, l);
- packet_unref(ctx->packet);
- free(ctx);
+ packet_unref(ctx->packet);
+ free(ctx);
}
static inline struct request_ctx *create_request_ctx(int handle)
{
- struct request_ctx *ctx;
+ struct request_ctx *ctx;
- ctx = malloc(sizeof(*ctx));
- if (!ctx) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
+ ctx = malloc(sizeof(*ctx));
+ if (!ctx) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return NULL;
+ }
- ctx->handle = handle;
- ctx->pid = (pid_t)-1;
- ctx->packet = NULL;
- ctx->recv_cb = NULL;
- ctx->data = NULL;
- ctx->inuse = 0;
+ ctx->handle = handle;
+ ctx->pid = (pid_t)-1;
+ ctx->packet = NULL;
+ ctx->recv_cb = NULL;
+ ctx->data = NULL;
+ ctx->inuse = 0;
- s_info.request_list = dlist_append(s_info.request_list, ctx);
- return ctx;
+ s_info.request_list = dlist_append(s_info.request_list, ctx);
+ return ctx;
}
static inline struct recv_ctx *find_recv_ctx(int handle)
{
- struct recv_ctx *ctx;
- struct dlist *l;
+ struct recv_ctx *ctx;
+ struct dlist *l;
- dlist_foreach(s_info.recv_list, l, ctx) {
- if (ctx->handle == handle) {
- return ctx;
- }
+ dlist_foreach(s_info.recv_list, l, ctx) {
+ if (ctx->handle == handle) {
+ return ctx;
}
+ }
- return NULL;
+ return NULL;
}
static inline void recreate_recv_ctx(struct recv_ctx *ctx)
{
- if (ctx->packet) {
- packet_destroy(ctx->packet);
- ctx->packet = NULL;
- }
- ctx->state = RECV_STATE_INIT;
- ctx->offset = 0;
- ctx->pid = (pid_t)-1;
- // ctx->inuse
- // ctx->handle
- // ctx->timeout
+ if (ctx->packet) {
+ packet_destroy(ctx->packet);
+ ctx->packet = NULL;
+ }
+ ctx->state = RECV_STATE_INIT;
+ ctx->offset = 0;
+ ctx->pid = (pid_t)-1;
+ // ctx->inuse
+ // ctx->handle
+ // ctx->timeout
}
static inline void destroy_recv_ctx(struct recv_ctx *ctx)
{
- struct dlist *l;
+ struct dlist *l;
- if (ctx->inuse) {
- return;
- }
+ if (ctx->inuse) {
+ return;
+ }
- l = dlist_find_data(s_info.recv_list, ctx);
- if (!l) {
- return;
- }
+ l = dlist_find_data(s_info.recv_list, ctx);
+ if (!l) {
+ return;
+ }
- s_info.recv_list = dlist_remove(s_info.recv_list, l);
+ s_info.recv_list = dlist_remove(s_info.recv_list, l);
- packet_destroy(ctx->packet);
- free(ctx);
+ packet_destroy(ctx->packet);
+ free(ctx);
}
static inline struct recv_ctx *create_recv_ctx(int handle, double timeout)
{
- struct recv_ctx *ctx;
+ struct recv_ctx *ctx;
- ctx = malloc(sizeof(*ctx));
- if (!ctx) {
- ErrPrint("heap: %s\n", strerror(errno));
- return NULL;
- }
+ ctx = malloc(sizeof(*ctx));
+ if (!ctx) {
+ ErrPrint("heap: %s\n", strerror(errno));
+ return NULL;
+ }
- ctx->state = RECV_STATE_INIT,
+ ctx->state = RECV_STATE_INIT,
ctx->offset = 0;
- ctx->packet = NULL;
- ctx->handle = handle;
- ctx->pid = (pid_t)-1;
- ctx->timeout = timeout;
- ctx->inuse = 0;
-
- s_info.recv_list = dlist_append(s_info.recv_list, ctx);
- return ctx;
+ ctx->packet = NULL;
+ ctx->handle = handle;
+ ctx->pid = (pid_t)-1;
+ ctx->timeout = timeout;
+ ctx->inuse = 0;
+
+ s_info.recv_list = dlist_append(s_info.recv_list, ctx);
+ return ctx;
}
static inline int packet_ready(int handle, struct recv_ctx *receive, struct method *table)
{
- struct request_ctx *request;
- double sequence;
- struct packet *result;
- register int i;
- int ret;
- const char *cmd;
- unsigned int cmd_idx;
+ struct request_ctx *request;
+ double sequence;
+ struct packet *result;
+ register int i;
+ int ret;
+ const char *cmd;
+ unsigned int cmd_idx;
- ret = 0;
+ ret = 0;
- switch (packet_type(receive->packet)) {
+ switch (packet_type(receive->packet)) {
case PACKET_ACK:
- sequence = packet_seq(receive->packet);
- request = find_request_ctx(handle, sequence);
- if (!request) {
- ErrPrint("This is not requested packet (%s)\n", packet_command(receive->packet));
- break;
- }
-
- if (request->recv_cb) {
- request->inuse = 1;
- receive->inuse = 1;
- request->recv_cb(receive->pid, handle, receive->packet, request->data);
- receive->inuse = 0;
- request->inuse = 0;
- }
-
- destroy_request_ctx(request);
+ sequence = packet_seq(receive->packet);
+ request = find_request_ctx(handle, sequence);
+ if (!request) {
+ ErrPrint("This is not requested packet (%s)\n", packet_command(receive->packet));
break;
+ }
+
+ if (request->recv_cb) {
+ request->inuse = 1;
+ receive->inuse = 1;
+ request->recv_cb(receive->pid, handle, receive->packet, request->data);
+ receive->inuse = 0;
+ request->inuse = 0;
+ }
+
+ destroy_request_ctx(request);
+ break;
case PACKET_REQ:
- cmd_idx = 0xFFFFFFFF;
- cmd = packet_command(receive->packet);
- if (cmd[0] == PACKET_CMD_INT_TAG) {
- unsigned int *p_cmd_idx = (unsigned int *)cmd;
-
- /* Get rid of LSB 8 bits */
- cmd_idx = *p_cmd_idx >> 8;
- } else {
- for (i = 0; table[i].cmd; i++) {
- if (strcmp(table[i].cmd, packet_command(receive->packet))) {
- continue;
- }
-
- cmd_idx = (unsigned int)i;
- break;
- }
- }
+ cmd_idx = 0xFFFFFFFF;
+ cmd = packet_command(receive->packet);
+ if (cmd[0] == PACKET_CMD_INT_TAG) {
+ unsigned int *p_cmd_idx = (unsigned int *)cmd;
+
+ /* Get rid of LSB 8 bits */
+ cmd_idx = *p_cmd_idx >> 8;
+ } else {
+ for (i = 0; table[i].cmd; i++) {
+ if (strcmp(table[i].cmd, packet_command(receive->packet))) {
+ continue;
+ }
- if (cmd_idx != 0xFFFFFFFF) {
- receive->inuse = 1;
- result = table[cmd_idx].handler(receive->pid, handle, receive->packet);
- receive->inuse = 0;
- if (result) {
- ret = s_info.vtable.send(handle, (void *)packet_data(result), packet_size(result), DEFAULT_TIMEOUT);
- if (ret < 0) {
- ErrPrint("Failed to send an ack packet\n");
- } else {
- ret = 0;
- }
- packet_destroy(result);
- }
+ cmd_idx = (unsigned int)i;
+ break;
}
+ }
+
+ if (cmd_idx != 0xFFFFFFFF) {
+ receive->inuse = 1;
+ result = table[cmd_idx].handler(receive->pid, handle, receive->packet);
+ receive->inuse = 0;
+ if (result) {
+ ret = s_info.vtable.send(handle, (void *)packet_data(result), packet_size(result), DEFAULT_TIMEOUT);
+ if (ret < 0) {
+ ErrPrint("Failed to send an ack packet\n");
+ } else {
+ ret = 0;
+ }
+ packet_destroy(result);
+ }
+ }
- break;
+ break;
case PACKET_REQ_NOACK:
- cmd_idx = 0xFFFFFFFF;
- cmd = packet_command(receive->packet);
- if (cmd[0] == PACKET_CMD_INT_TAG) {
- unsigned int *p_cmd_idx = (unsigned int *)cmd;
-
- /* Get rid of LSB 8 bits */
- cmd_idx = *p_cmd_idx >> 8;
- } else {
- for (i = 0; table[i].cmd; i++) {
- if (strcmp(table[i].cmd, packet_command(receive->packet))) {
- continue;
- }
-
- cmd_idx = (unsigned int)i;
- break;
- }
+ cmd_idx = 0xFFFFFFFF;
+ cmd = packet_command(receive->packet);
+ if (cmd[0] == PACKET_CMD_INT_TAG) {
+ unsigned int *p_cmd_idx = (unsigned int *)cmd;
+
+ /* Get rid of LSB 8 bits */
+ cmd_idx = *p_cmd_idx >> 8;
+ } else {
+ for (i = 0; table[i].cmd; i++) {
+ if (strcmp(table[i].cmd, packet_command(receive->packet))) {
+ continue;
+ }
+
+ cmd_idx = (unsigned int)i;
+ break;
}
+ }
- if (cmd_idx != 0xFFFFFFFF) {
- receive->inuse = 1;
- result = table[cmd_idx].handler(receive->pid, handle, receive->packet);
- receive->inuse = 0;
- if (result) {
- packet_destroy(result);
- }
+ if (cmd_idx != 0xFFFFFFFF) {
+ receive->inuse = 1;
+ result = table[cmd_idx].handler(receive->pid, handle, receive->packet);
+ receive->inuse = 0;
+ if (result) {
+ packet_destroy(result);
}
- break;
+ }
+ break;
default:
- break;
- }
+ break;
+ }
- /*!
- * Return negative value will make call the disconnected_cb
- */
- return ret;
+ /*!
+ * Return negative value will make call the disconnected_cb
+ */
+ return ret;
}
static int client_disconnected_cb(int handle, void *data)
{
- struct recv_ctx *receive;
- struct request_ctx *request;
- struct dlist *l;
- struct dlist *n;
- int inuse_found = 0;
- pid_t pid = (pid_t)-1;
-
- receive = find_recv_ctx(handle);
- if (receive) {
- pid = receive->pid;
- }
-
- DbgPrint("Clean up all requests and a receive context for handle(%d) for pid(%d)\n", handle, pid);
+ struct recv_ctx *receive;
+ struct request_ctx *request;
+ struct dlist *l;
+ struct dlist *n;
+ int inuse_found = 0;
+ pid_t pid = (pid_t)-1;
- dlist_foreach_safe(s_info.request_list, l, n, request) {
- if (request->handle != handle) {
- continue;
- }
+ receive = find_recv_ctx(handle);
+ if (receive) {
+ pid = receive->pid;
+ }
- if (request->inuse) {
- inuse_found = 1;
- continue;
- }
+ DbgPrint("Clean up all requests and a receive context for handle(%d) for pid(%d)\n", handle, pid);
- if (request->recv_cb) {
- request->recv_cb(pid, handle, NULL, request->data);
- }
+ dlist_foreach_safe(s_info.request_list, l, n, request) {
+ if (request->handle != handle) {
+ continue;
+ }
- destroy_request_ctx(request);
+ if (request->inuse) {
+ inuse_found = 1;
+ continue;
}
- if (receive && !inuse_found) {
- destroy_recv_ctx(receive);
+ if (request->recv_cb) {
+ request->recv_cb(pid, handle, NULL, request->data);
}
- return 0;
+ destroy_request_ctx(request);
+ }
+
+ if (receive && !inuse_found) {
+ destroy_recv_ctx(receive);
+ }
+
+ return 0;
}
static int service_cb(int handle, void *data)
{
- struct recv_ctx *receive;
- pid_t pid;
- int ret;
- int size;
- char *ptr;
-
- receive = find_recv_ctx(handle);
+ struct recv_ctx *receive;
+ pid_t pid;
+ int ret;
+ int size;
+ char *ptr;
+
+ receive = find_recv_ctx(handle);
+ if (!receive) {
+ receive = create_recv_ctx(handle, DEFAULT_TIMEOUT);
if (!receive) {
- receive = create_recv_ctx(handle, DEFAULT_TIMEOUT);
- if (!receive) {
- ErrPrint("Couldn't find or create a receive context\n");
- return -EIO;
- }
+ ErrPrint("Couldn't find or create a receive context\n");
+ return -EIO;
}
+ }
- switch (receive->state) {
+ switch (receive->state) {
case RECV_STATE_INIT:
- receive->state = RECV_STATE_HEADER;
- receive->offset = 0;
+ receive->state = RECV_STATE_HEADER;
+ receive->offset = 0;
case RECV_STATE_HEADER:
- size = packet_header_size() - receive->offset;
- /*!
- * \note
- * Getting header
- */
- ptr = malloc(size);
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return -ENOMEM;
+ size = packet_header_size() - receive->offset;
+ /*!
+ * \note
+ * Getting header
+ */
+ ptr = malloc(size);
+ if (!ptr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ ret = s_info.vtable.recv(handle, ptr, size, &pid, receive->timeout);
+ if (ret < 0) {
+ ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
+ free(ptr);
+ return -EIO; /*!< Return negative value will invoke the client_disconnected_cb */
+ } else if (ret > 0) {
+ if (receive->pid != -1 && receive->pid != pid) {
+ ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
+ free(ptr);
+ return -EIO; /*!< Return negative value will invoke the client_disconnected_cb */
}
- ret = s_info.vtable.recv(handle, ptr, size, &pid, receive->timeout);
- if (ret < 0) {
- ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
- free(ptr);
- return -EIO; /*!< Return negative value will invoke the client_disconnected_cb */
- } else if (ret > 0) {
- if (receive->pid != -1 && receive->pid != pid) {
- ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
- free(ptr);
- return -EIO; /*!< Return negative value will invoke the client_disconnected_cb */
- }
-
- receive->pid = pid;
- receive->packet = packet_build(receive->packet, receive->offset, ptr, ret);
- free(ptr);
-
- if (!receive->packet) {
- ErrPrint("Built packet is not valid\n");
- return -EFAULT; /*!< Return negative value will invoke the client_disconnected_cb */
- }
-
- receive->offset += ret;
-
- if (receive->offset == packet_header_size()) {
- if (packet_size(receive->packet) == receive->offset) {
- receive->state = RECV_STATE_READY;
- } else {
- receive->state = RECV_STATE_BODY;
- }
- }
- } else {
- DbgPrint("ZERO bytes receives(%d)\n", pid);
- free(ptr);
- return -ECONNRESET;
+ receive->pid = pid;
+ receive->packet = packet_build(receive->packet, receive->offset, ptr, ret);
+ free(ptr);
+
+ if (!receive->packet) {
+ ErrPrint("Built packet is not valid\n");
+ return -EFAULT; /*!< Return negative value will invoke the client_disconnected_cb */
}
- break;
- case RECV_STATE_BODY:
- size = packet_size(receive->packet) - receive->offset;
- if (size == 0) {
+
+ receive->offset += ret;
+
+ if (receive->offset == packet_header_size()) {
+ if (packet_size(receive->packet) == receive->offset) {
receive->state = RECV_STATE_READY;
- break;
+ } else {
+ receive->state = RECV_STATE_BODY;
+ }
}
- /*!
- * \note
- * Getting body
- */
- ptr = malloc(size);
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return -ENOMEM;
+ } else {
+ DbgPrint("ZERO bytes receives(%d)\n", pid);
+ free(ptr);
+ return -ECONNRESET;
+ }
+ break;
+ case RECV_STATE_BODY:
+ size = packet_size(receive->packet) - receive->offset;
+ if (size == 0) {
+ receive->state = RECV_STATE_READY;
+ break;
+ }
+ /*!
+ * \note
+ * Getting body
+ */
+ ptr = malloc(size);
+ if (!ptr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ ret = s_info.vtable.recv(handle, ptr, size, &pid, receive->timeout);
+ if (ret < 0) {
+ ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
+ free(ptr);
+ return -EIO;
+ } else if (ret > 0) {
+ if (receive->pid != pid) {
+ ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
+ free(ptr);
+ return -EIO;
}
- ret = s_info.vtable.recv(handle, ptr, size, &pid, receive->timeout);
- if (ret < 0) {
- ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
- free(ptr);
- return -EIO;
- } else if (ret > 0) {
- if (receive->pid != pid) {
- ErrPrint("Recv[%d], pid[%d :: %d]\n", ret, receive->pid, pid);
- free(ptr);
- return -EIO;
- }
-
- receive->packet = packet_build(receive->packet, receive->offset, ptr, ret);
- free(ptr);
-
- if (!receive->packet) {
- ErrPrint("Built packet is not valid\n");
- return -EFAULT;
- }
-
- receive->offset += ret;
-
- if (receive->offset == packet_size(receive->packet)) {
- receive->state = RECV_STATE_READY;
- }
- } else {
- DbgPrint("ZERO bytes receives(%d)\n", pid);
- free(ptr);
- return -ECONNRESET;
+ receive->packet = packet_build(receive->packet, receive->offset, ptr, ret);
+ free(ptr);
+
+ if (!receive->packet) {
+ ErrPrint("Built packet is not valid\n");
+ return -EFAULT;
}
- break;
+ receive->offset += ret;
+
+ if (receive->offset == packet_size(receive->packet)) {
+ receive->state = RECV_STATE_READY;
+ }
+ } else {
+ DbgPrint("ZERO bytes receives(%d)\n", pid);
+ free(ptr);
+ return -ECONNRESET;
+ }
+
+ break;
case RECV_STATE_READY:
default:
- break;
- }
+ break;
+ }
- if (receive->state == RECV_STATE_READY) {
- ret = packet_ready(handle, receive, data);
- if (ret == 0) {
- /*!
- * If ret is negative value, the receive context will be destroyed from disconnected callback
- */
- recreate_recv_ctx(receive);
- }
- /*!
- * if ret is negative value, disconnected_cb will be called after this function
- */
- } else {
- ret = 0;
+ if (receive->state == RECV_STATE_READY) {
+ ret = packet_ready(handle, receive, data);
+ if (ret == 0) {
+ /*!
+ * If ret is negative value, the receive context will be destroyed from disconnected callback
+ */
+ recreate_recv_ctx(receive);
}
+ /*!
+ * if ret is negative value, disconnected_cb will be called after this function
+ */
+ } else {
+ ret = 0;
+ }
- return ret;
+ return ret;
}
EAPI int com_core_packet_async_send(int handle, struct packet *packet, double timeout, int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data), void *data)
{
- int ret;
- struct request_ctx *ctx;
-
- if (handle < 0 || !packet) {
- ErrPrint("Invalid argument\n");
- return -EINVAL;
- }
-
- if (packet_type(packet) != PACKET_REQ) {
- ErrPrint("Invalid packet - should be PACKET_REQ\n");
- return -EINVAL;
- }
-
- ctx = create_request_ctx(handle);
- if (!ctx) {
- return -ENOMEM;
- }
-
- ctx->recv_cb = recv_cb;
- ctx->data = data;
- ctx->packet = packet_ref(packet);
-
- ret = s_info.vtable.send(handle, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
- if (ret != packet_size(packet)) {
- ErrPrint("Send failed. %d <> %d (handle: %d)\n", ret, packet_size(packet), handle);
- destroy_request_ctx(ctx);
- return -EIO;
- }
-
- return 0;
+ int ret;
+ struct request_ctx *ctx;
+
+ if (handle < 0 || !packet) {
+ ErrPrint("Invalid argument\n");
+ return -EINVAL;
+ }
+
+ if (packet_type(packet) != PACKET_REQ) {
+ ErrPrint("Invalid packet - should be PACKET_REQ\n");
+ return -EINVAL;
+ }
+
+ ctx = create_request_ctx(handle);
+ if (!ctx) {
+ return -ENOMEM;
+ }
+
+ ctx->recv_cb = recv_cb;
+ ctx->data = data;
+ ctx->packet = packet_ref(packet);
+
+ ret = s_info.vtable.send(handle, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
+ if (ret != packet_size(packet)) {
+ ErrPrint("Send failed. %d <> %d (handle: %d)\n", ret, packet_size(packet), handle);
+ destroy_request_ctx(ctx);
+ return -EIO;
+ }
+
+ return 0;
}
EAPI int com_core_packet_send_only(int handle, struct packet *packet)
{
- int ret;
+ int ret;
- if (packet_type(packet) != PACKET_REQ_NOACK) {
- ErrPrint("Invalid type - should be PACKET_REQ_NOACK (%p)\n", packet);
- return -EINVAL;
- }
+ if (packet_type(packet) != PACKET_REQ_NOACK) {
+ ErrPrint("Invalid type - should be PACKET_REQ_NOACK (%p)\n", packet);
+ return -EINVAL;
+ }
- ret = s_info.vtable.send(handle, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
- if (ret != packet_size(packet)) {
- ErrPrint("Failed to send whole packet\n");
- return -EIO;
- }
+ ret = s_info.vtable.send(handle, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
+ if (ret != packet_size(packet)) {
+ ErrPrint("Failed to send whole packet\n");
+ return -EIO;
+ }
- return 0;
+ return 0;
}
EAPI struct packet *com_core_packet_oneshot_send(const char *addr, struct packet *packet, double timeout)
{
- int ret;
- int fd;
- pid_t pid;
- int offset;
- struct packet *result = NULL;
- void *ptr;
- int size;
-
- if (!addr || !packet) {
- ErrPrint("Invalid argument\n");
- return NULL;
- }
-
- fd = secure_socket_create_client(addr);
- if (fd < 0) {
- return NULL;
- }
-
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
-
- ret = com_core_send(fd, (char *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
- if (ret < 0) {
- goto out;
- }
-
- ptr = malloc(packet_header_size());
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- goto out;
- }
-
- offset = 0;
- ret = com_core_recv(fd, (char *)ptr, packet_header_size(), &pid, timeout);
- if (ret <= 0) {
- DbgPrint("Recv returns %d\n", ret);
- free(ptr);
- goto out;
- } else {
- DbgPrint("Recv'd size: %d (header: %d) pid: %d\n", ret, packet_header_size(), pid);
- result = packet_build(result, offset, ptr, ret);
- offset += ret;
- free(ptr);
- if (!result) {
- ErrPrint("Failed to build a packet\n");
- goto out;
- }
- }
-
- size = packet_payload_size(result);
- if (size < 0) {
- packet_destroy(result);
- result = NULL;
- goto out;
- }
-
- if (size == 0) {
- DbgPrint("Has no payload\n");
- goto out;
- }
-
- ptr = malloc(size);
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- packet_destroy(result);
- result = NULL;
- goto out;
- }
+ int ret;
+ int fd;
+ pid_t pid;
+ int offset;
+ struct packet *result = NULL;
+ void *ptr;
+ int size;
+
+ if (!addr || !packet) {
+ ErrPrint("Invalid argument\n");
+ return NULL;
+ }
- ret = com_core_recv(fd, (char *)ptr, size, &pid, timeout);
- if (ret <= 0) {
- DbgPrint("Recv returns %d\n", ret);
- free(ptr);
- packet_destroy(result);
- result = NULL;
- } else {
- DbgPrint("Recv'd %d bytes (pid: %d)\n", ret, pid);
- result = packet_build(result, offset, ptr, ret);
- offset += ret;
- free(ptr);
- }
+ fd = secure_socket_create_client(addr);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("fcntl: %s\n", strerror(errno));
+ }
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+
+ ret = com_core_send(fd, (char *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
+ if (ret < 0) {
+ goto out;
+ }
+
+ ptr = malloc(packet_header_size());
+ if (!ptr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ goto out;
+ }
+
+ offset = 0;
+ ret = com_core_recv(fd, (char *)ptr, packet_header_size(), &pid, timeout);
+ if (ret <= 0) {
+ DbgPrint("Recv returns %d\n", ret);
+ free(ptr);
+ goto out;
+ } else {
+ DbgPrint("Recv'd size: %d (header: %d) pid: %d\n", ret, packet_header_size(), pid);
+ result = packet_build(result, offset, ptr, ret);
+ offset += ret;
+ free(ptr);
+ if (!result) {
+ ErrPrint("Failed to build a packet\n");
+ goto out;
+ }
+ }
+
+ size = packet_payload_size(result);
+ if (size < 0) {
+ packet_destroy(result);
+ result = NULL;
+ goto out;
+ }
+
+ if (size == 0) {
+ DbgPrint("Has no payload\n");
+ goto out;
+ }
+
+ ptr = malloc(size);
+ if (!ptr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ packet_destroy(result);
+ result = NULL;
+ goto out;
+ }
+
+ ret = com_core_recv(fd, (char *)ptr, size, &pid, timeout);
+ if (ret <= 0) {
+ DbgPrint("Recv returns %d\n", ret);
+ free(ptr);
+ packet_destroy(result);
+ result = NULL;
+ } else {
+ DbgPrint("Recv'd %d bytes (pid: %d)\n", ret, pid);
+ result = packet_build(result, offset, ptr, ret);
+ offset += ret;
+ free(ptr);
+ }
out:
- secure_socket_destroy_handle(fd);
- DbgPrint("Close connection: %d\n", fd);
- return result;
+ secure_socket_destroy_handle(fd);
+ DbgPrint("Close connection: %d\n", fd);
+ return result;
}
static inline int com_core_packet_init(void)
{
- int ret;
- if (s_info.initialized) {
- return 0;
- }
+ int ret;
+ if (s_info.initialized) {
+ return 0;
+ }
- ret = com_core_add_event_callback(CONNECTOR_DISCONNECTED, client_disconnected_cb, NULL);
- s_info.initialized = (ret == 0);
- return ret;
+ ret = com_core_add_event_callback(CONNECTOR_DISCONNECTED, client_disconnected_cb, NULL);
+ s_info.initialized = (ret == 0);
+ return ret;
}
static inline int com_core_packet_fini(void)
{
- if (!s_info.initialized) {
- return 0;
- }
-
- s_info.initialized = 0;
- com_core_del_event_callback(CONNECTOR_DISCONNECTED, client_disconnected_cb, NULL);
+ if (!s_info.initialized) {
return 0;
+ }
+
+ s_info.initialized = 0;
+ com_core_del_event_callback(CONNECTOR_DISCONNECTED, client_disconnected_cb, NULL);
+ return 0;
}
EAPI int com_core_packet_client_init(const char *addr, int is_sync, struct method *table)
{
- int ret;
+ int ret;
- ret = com_core_packet_init();
- if (ret < 0) {
- return ret;
- }
+ ret = com_core_packet_init();
+ if (ret < 0) {
+ return ret;
+ }
- ret = s_info.vtable.client_create(addr, is_sync, service_cb, table);
- if (ret < 0) {
- com_core_packet_fini();
- }
+ ret = s_info.vtable.client_create(addr, is_sync, service_cb, table);
+ if (ret < 0) {
+ com_core_packet_fini();
+ }
- return ret;
+ return ret;
}
EAPI int com_core_packet_client_fini(int handle)
{
- s_info.vtable.client_destroy(handle);
- com_core_packet_fini();
- return 0;
+ s_info.vtable.client_destroy(handle);
+ com_core_packet_fini();
+ return 0;
}
EAPI int com_core_packet_server_init(const char *addr, struct method *table)
{
- int ret;
+ int ret;
- ret = com_core_packet_init();
- if (ret < 0) {
- return ret;
- }
+ ret = com_core_packet_init();
+ if (ret < 0) {
+ return ret;
+ }
- ret = s_info.vtable.server_create(addr, 0, service_cb, table);
- if (ret < 0) {
- com_core_packet_fini();
- }
+ ret = s_info.vtable.server_create(addr, 0, service_cb, table);
+ if (ret < 0) {
+ com_core_packet_fini();
+ }
- return ret;
+ return ret;
}
EAPI int com_core_packet_server_fini(int handle)
{
- s_info.vtable.server_destroy(handle);
- com_core_packet_fini();
- return 0;
+ s_info.vtable.server_destroy(handle);
+ com_core_packet_fini();
+ return 0;
}
EAPI void com_core_packet_use_thread(int flag)
{
- if (!!flag) {
- s_info.vtable.server_create = com_core_thread_server_create;
- s_info.vtable.client_create = com_core_thread_client_create;
- s_info.vtable.server_destroy = com_core_thread_server_destroy;
- s_info.vtable.client_destroy = com_core_thread_client_destroy;
- s_info.vtable.recv = com_core_thread_recv;
- s_info.vtable.send = com_core_thread_send;
- } else {
- s_info.vtable.server_create = com_core_server_create;
- s_info.vtable.client_create = com_core_client_create;
- s_info.vtable.server_destroy = com_core_server_destroy;
- s_info.vtable.client_destroy = com_core_client_destroy;
- s_info.vtable.recv = com_core_recv;
- s_info.vtable.send = com_core_send;
- }
+ if (s_info.initialized) {
+ ErrPrint("com-core method is in use\n");
+ return;
+ }
+
+ if (!!flag) {
+ s_info.vtable.server_create = com_core_thread_server_create;
+ s_info.vtable.client_create = com_core_thread_client_create;
+ s_info.vtable.server_destroy = com_core_thread_server_destroy;
+ s_info.vtable.client_destroy = com_core_thread_client_destroy;
+ s_info.vtable.recv = com_core_thread_recv;
+ s_info.vtable.send = com_core_thread_send;
+ s_info.vtable.recv_with_fd = com_core_thread_recv_with_fd;
+ s_info.vtable.send_with_fd = com_core_thread_send_with_fd;
+ } else {
+ s_info.vtable.server_create = com_core_server_create;
+ s_info.vtable.client_create = com_core_client_create;
+ s_info.vtable.server_destroy = com_core_server_destroy;
+ s_info.vtable.client_destroy = com_core_client_destroy;
+ s_info.vtable.recv = com_core_recv;
+ s_info.vtable.send = com_core_send;
+ s_info.vtable.recv_with_fd = com_core_recv_with_fd;
+ s_info.vtable.send_with_fd = com_core_send_with_fd;
+ }
}
/* End of a file */
diff --git a/src/com-core_thread.c b/src/com-core_thread.c
index f5fc9c6..42348c6 100644
--- a/src/com-core_thread.c
+++ b/src/com-core_thread.c
@@ -41,76 +41,77 @@ int errno;
#define EVENT_TERM 'e'
static struct {
- struct dlist *tcb_list;
- struct dlist *server_list;
+ struct dlist *tcb_list;
+ struct dlist *server_list;
} s_info = {
- .tcb_list = NULL,
- .server_list = NULL,
+ .tcb_list = NULL,
+ .server_list = NULL,
};
/*!
* \brief Representing the Server Object
*/
struct server {
- int (*service_cb)(int fd, void *data);
- void *data;
+ int (*service_cb)(int fd, void *data);
+ void *data;
- guint id;
- int handle;
+ guint id;
+ int handle;
};
/*!
* \brief This is used to holds a packet
*/
struct chunk {
- char *data;
- int offset;
- int size;
- pid_t pid;
+ char *data;
+ int offset;
+ int size;
+ pid_t pid;
+ int fd;
};
/*!
* \brief Thread Control Block
*/
struct tcb {
- pthread_t thid;
- int handle;
- struct dlist *chunk_list;
- int evt_pipe[PIPE_MAX];
- int ctrl_pipe[PIPE_MAX];
- pthread_mutex_t chunk_lock;
- guint id; /*!< g_io_watch */
-
- int server_handle;
-
- int (*service_cb)(int fd, void *data);
- void *data;
+ pthread_t thid;
+ int handle;
+ struct dlist *chunk_list;
+ int evt_pipe[PIPE_MAX];
+ int ctrl_pipe[PIPE_MAX];
+ pthread_mutex_t chunk_lock;
+ guint id; /*!< g_io_watch */
+
+ int server_handle;
+
+ int (*service_cb)(int fd, void *data);
+ void *data;
};
static ssize_t write_safe(int fd, const void *data, size_t bufsz)
{
- int ret;
- int again;
-
- do {
- again = 0;
- ret = write(fd, data, bufsz);
- if (ret < 0) {
- ret = -errno;
- switch (ret) {
- case -EAGAIN:
- case -EINTR:
- again = 1;
- ErrPrint("Interrupted[%d] Again[%d]\n", fd, -ret);
- break;
- default:
- ErrPrint("Failed to write: %s (%d)\n", strerror(-ret), -ret);
- return ret;
- }
- }
- } while (again);
+ int ret;
+ int again;
- return ret;
+ do {
+ again = 0;
+ ret = write(fd, data, bufsz);
+ if (ret < 0) {
+ ret = -errno;
+ switch (ret) {
+ case -EAGAIN:
+ case -EINTR:
+ again = 1;
+ ErrPrint("Interrupted[%d] Again[%d]\n", fd, -ret);
+ break;
+ default:
+ ErrPrint("Failed to write: %s (%d)\n", strerror(-ret), -ret);
+ return ret;
+ }
+ }
+ } while (again);
+
+ return ret;
}
/*!
@@ -119,17 +120,17 @@ static ssize_t write_safe(int fd, const void *data, size_t bufsz)
*/
static inline void server_destroy(struct server *server)
{
- dlist_remove_data(s_info.server_list, server);
+ dlist_remove_data(s_info.server_list, server);
- if (server->id > 0) {
- g_source_remove(server->id);
- }
+ if (server->id > 0) {
+ g_source_remove(server->id);
+ }
- if (server->handle > 0) {
- secure_socket_destroy_handle(server->handle);
- }
+ if (server->handle > 0) {
+ secure_socket_destroy_handle(server->handle);
+ }
- free(server);
+ free(server);
}
/*!
@@ -138,20 +139,20 @@ static inline void server_destroy(struct server *server)
*/
static inline struct server *server_create(int handle, int (*service_cb)(int fd, void *data), void *data)
{
- struct server *server;
+ struct server *server;
- server = malloc(sizeof(*server));
- if (!server) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
+ server = malloc(sizeof(*server));
+ if (!server) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return NULL;
+ }
- server->handle = handle;
- server->service_cb = service_cb;
- server->data = data;
+ server->handle = handle;
+ server->service_cb = service_cb;
+ server->data = data;
- s_info.server_list = dlist_append(s_info.server_list, server);
- return server;
+ s_info.server_list = dlist_append(s_info.server_list, server);
+ return server;
}
/*!
@@ -160,8 +161,8 @@ static inline struct server *server_create(int handle, int (*service_cb)(int fd,
*/
static inline void destroy_chunk(struct chunk *chunk)
{
- free(chunk->data);
- free(chunk);
+ free(chunk->data);
+ free(chunk);
}
/*!
@@ -170,33 +171,33 @@ static inline void destroy_chunk(struct chunk *chunk)
*/
static inline void terminate_thread(struct tcb *tcb)
{
- int status;
- struct dlist *l;
- struct dlist *n;
- void *res = NULL;
- struct chunk *chunk;
-
- if (write_safe(tcb->ctrl_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
- ErrPrint("Unable to write CTRL pipe (%d)\n", sizeof(tcb));
- }
-
- secure_socket_destroy_handle(tcb->handle);
-
- status = pthread_join(tcb->thid, &res);
- if (status != 0) {
- ErrPrint("Join: %s\n", strerror(status));
- } else {
- ErrPrint("Thread returns: %d\n", (int)res);
- }
-
- dlist_foreach_safe(tcb->chunk_list, l, n, chunk) {
- /*!
- * Discarding all packets
- */
- DbgPrint("Discarding chunks\n");
- tcb->chunk_list = dlist_remove(tcb->chunk_list, l);
- destroy_chunk(chunk);
- }
+ int status;
+ struct dlist *l;
+ struct dlist *n;
+ void *res = NULL;
+ struct chunk *chunk;
+
+ if (write_safe(tcb->ctrl_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
+ ErrPrint("Unable to write CTRL pipe (%d)\n", sizeof(tcb));
+ }
+
+ secure_socket_destroy_handle(tcb->handle);
+
+ status = pthread_join(tcb->thid, &res);
+ if (status != 0) {
+ ErrPrint("Join: %s\n", strerror(status));
+ } else {
+ ErrPrint("Thread returns: %d\n", (int)res);
+ }
+
+ dlist_foreach_safe(tcb->chunk_list, l, n, chunk) {
+ /*!
+ * Discarding all packets
+ */
+ DbgPrint("Discarding chunks\n");
+ tcb->chunk_list = dlist_remove(tcb->chunk_list, l);
+ destroy_chunk(chunk);
+ }
}
/*!
@@ -205,21 +206,21 @@ static inline void terminate_thread(struct tcb *tcb)
*/
static inline void chunk_remove(struct tcb *tcb, struct chunk *chunk)
{
- char event_ch;
+ char event_ch;
- /* Consuming the event */
- if (read(tcb->evt_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("Failed to get readsize\n");
- return;
- }
+ /* Consuming the event */
+ if (read(tcb->evt_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("Failed to get readsize\n");
+ return;
+ }
- CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
+ CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
- dlist_remove_data(tcb->chunk_list, chunk);
+ dlist_remove_data(tcb->chunk_list, chunk);
- CRITICAL_SECTION_END(&tcb->chunk_lock);
+ CRITICAL_SECTION_END(&tcb->chunk_lock);
- destroy_chunk(chunk);
+ destroy_chunk(chunk);
}
/*!
@@ -228,32 +229,32 @@ static inline void chunk_remove(struct tcb *tcb, struct chunk *chunk)
*/
static inline int chunk_append(struct tcb *tcb, struct chunk *chunk)
{
- char event_ch = EVENT_READY;
- int ret;
+ char event_ch = EVENT_READY;
+ int ret;
- CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
+ CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
- tcb->chunk_list = dlist_append(tcb->chunk_list, chunk);
+ tcb->chunk_list = dlist_append(tcb->chunk_list, chunk);
- CRITICAL_SECTION_END(&tcb->chunk_lock);
+ CRITICAL_SECTION_END(&tcb->chunk_lock);
- ret = write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch));
- if (ret < 0) {
- CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
+ ret = write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch));
+ if (ret < 0) {
+ CRITICAL_SECTION_BEGIN(&tcb->chunk_lock);
- dlist_remove_data(tcb->chunk_list, chunk);
+ dlist_remove_data(tcb->chunk_list, chunk);
- CRITICAL_SECTION_END(&tcb->chunk_lock);
- return ret;
- }
+ CRITICAL_SECTION_END(&tcb->chunk_lock);
+ return ret;
+ }
- if (ret != sizeof(event_ch)) {
- ErrPrint("Failed to trigger reader\n");
- }
+ if (ret != sizeof(event_ch)) {
+ ErrPrint("Failed to trigger reader\n");
+ }
- /* Take a breathe */
- pthread_yield();
- return 0;
+ /* Take a breathe */
+ pthread_yield();
+ return 0;
}
/*!
@@ -262,44 +263,44 @@ static inline int chunk_append(struct tcb *tcb, struct chunk *chunk)
*/
static inline int wait_event(struct tcb *tcb, double timeout)
{
- fd_set set;
- int ret;
-
- FD_ZERO(&set);
- FD_SET(tcb->evt_pipe[PIPE_READ], &set);
-
- if (timeout > 0.0f) {
- struct timeval tv;
- tv.tv_sec = (unsigned long)timeout;
- tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
- ret = select(tcb->evt_pipe[PIPE_READ] + 1, &set, NULL, NULL, &tv);
- } else if (timeout == 0.0f) {
- ret = select(tcb->evt_pipe[PIPE_READ] + 1, &set, NULL, NULL, NULL);
- } else {
- ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
- return -EINVAL;
+ fd_set set;
+ int ret;
+
+ FD_ZERO(&set);
+ FD_SET(tcb->evt_pipe[PIPE_READ], &set);
+
+ if (timeout > 0.0f) {
+ struct timeval tv;
+ tv.tv_sec = (unsigned long)timeout;
+ tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
+ ret = select(tcb->evt_pipe[PIPE_READ] + 1, &set, NULL, NULL, &tv);
+ } else if (timeout == 0.0f) {
+ ret = select(tcb->evt_pipe[PIPE_READ] + 1, &set, NULL, NULL, NULL);
+ } else {
+ ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
+ return -EINVAL;
+ }
+
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EINTR) {
+ DbgPrint("Select receives INTR\n");
+ return -EAGAIN;
}
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- DbgPrint("Select receives INTR\n");
- return -EAGAIN;
- }
-
- ErrPrint("Error: %s\n", strerror(errno));
- return ret;
- } else if (ret == 0) {
- ErrPrint("Timeout expired\n");
- return -ETIMEDOUT;
- }
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ ErrPrint("Timeout expired\n");
+ return -ETIMEDOUT;
+ }
- if (!FD_ISSET(tcb->evt_pipe[PIPE_READ], &set)) {
- ErrPrint("Unexpected handle is toggled\n");
- return -EINVAL;
- }
+ if (!FD_ISSET(tcb->evt_pipe[PIPE_READ], &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ return -EINVAL;
+ }
- return 0;
+ return 0;
}
/*!
@@ -308,25 +309,26 @@ static inline int wait_event(struct tcb *tcb, double timeout)
*/
static inline struct chunk *create_chunk(int size)
{
- struct chunk *chunk;
+ struct chunk *chunk;
- chunk = malloc(sizeof(*chunk));
- if (!chunk) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
+ chunk = malloc(sizeof(*chunk));
+ if (!chunk) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return NULL;
+ }
- chunk->data = malloc(size);
- if (!chunk->data) {
- ErrPrint("Heap: %s\n", strerror(errno));
- free(chunk);
- return NULL;
- }
+ chunk->data = malloc(size);
+ if (!chunk->data) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ free(chunk);
+ return NULL;
+ }
- chunk->pid = (pid_t)-1;
- chunk->size = size;
- chunk->offset = 0;
- return chunk;
+ chunk->pid = (pid_t)-1;
+ chunk->size = size;
+ chunk->offset = 0;
+ chunk->fd = -1;
+ return chunk;
}
/*!
@@ -335,106 +337,106 @@ static inline struct chunk *create_chunk(int size)
*/
static void *client_cb(void *data)
{
- struct tcb *tcb = data;
- struct chunk *chunk;
- int ret = 0;
- fd_set set;
- int readsize;
- char event_ch;
- int fd;
-
- DbgPrint("Thread is created for %d (server: %d)\n", tcb->handle, tcb->server_handle);
- /*!
- * \NOTE
- * Read all data from the socket as possible as it can do
- */
- while (1) {
- FD_ZERO(&set);
- FD_SET(tcb->handle, &set);
- FD_SET(tcb->ctrl_pipe[PIPE_READ], &set);
-
- fd = tcb->handle > tcb->ctrl_pipe[PIPE_READ] ? tcb->handle : tcb->ctrl_pipe[PIPE_READ];
-
- ret = select(fd + 1, &set, NULL, NULL, NULL);
- if (ret < 0) {
- if (errno == EINTR) {
- DbgPrint("Select receives INTR\n");
- continue;
- }
- ret = -errno;
- /*!< Error */
- ErrPrint("Error: %s\n", strerror(errno));
- break;
- } else if (ret == 0) {
- ErrPrint("What happens? [%d]\n", tcb->handle);
- continue;
- }
+ struct tcb *tcb = data;
+ struct chunk *chunk;
+ int ret = 0;
+ fd_set set;
+ int readsize;
+ char event_ch;
+ int fd;
+
+ DbgPrint("Thread is created for %d (server: %d)\n", tcb->handle, tcb->server_handle);
+ /*!
+ * \NOTE
+ * Read all data from the socket as possible as it can do
+ */
+ while (1) {
+ FD_ZERO(&set);
+ FD_SET(tcb->handle, &set);
+ FD_SET(tcb->ctrl_pipe[PIPE_READ], &set);
- if (FD_ISSET(tcb->ctrl_pipe[PIPE_READ], &set)) {
- DbgPrint("Thread is canceled\n");
- ret = -ECANCELED;
- break;
- }
+ fd = tcb->handle > tcb->ctrl_pipe[PIPE_READ] ? tcb->handle : tcb->ctrl_pipe[PIPE_READ];
- if (!FD_ISSET(tcb->handle, &set)) {
- ErrPrint("Unexpected handle is toggled\n");
- ret = -EINVAL;
- break;
- }
+ ret = select(fd + 1, &set, NULL, NULL, NULL);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ DbgPrint("Select receives INTR\n");
+ continue;
+ }
+ ret = -errno;
+ /*!< Error */
+ ErrPrint("Error: %s\n", strerror(errno));
+ break;
+ } else if (ret == 0) {
+ ErrPrint("What happens? [%d]\n", tcb->handle);
+ continue;
+ }
- readsize = 0;
- ret = ioctl(tcb->handle, FIONREAD, &readsize);
- if (ret < 0) {
- ErrPrint("ioctl: %s\n", strerror(errno));
- break;
- }
+ if (FD_ISSET(tcb->ctrl_pipe[PIPE_READ], &set)) {
+ DbgPrint("Thread is canceled\n");
+ ret = -ECANCELED;
+ break;
+ }
- if (readsize <= 0) {
- ErrPrint("Available data: %d\n", readsize);
- ret = -ECONNRESET;
- break;
- }
+ if (!FD_ISSET(tcb->handle, &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ ret = -EINVAL;
+ break;
+ }
- chunk = create_chunk(readsize);
- if (!chunk) {
- ErrPrint("Failed to create a new chunk: %d\n", readsize);
- ret = -ENOMEM;
- break;
- }
+ readsize = 0;
+ ret = ioctl(tcb->handle, FIONREAD, &readsize);
+ if (ret < 0) {
+ ErrPrint("ioctl: %s\n", strerror(errno));
+ break;
+ }
- ret = secure_socket_recv(tcb->handle, chunk->data, chunk->size, &chunk->pid);
- if (ret <= 0) {
- destroy_chunk(chunk);
- if (ret == -EAGAIN) {
- DbgPrint("Retry to get data\n");
- continue;
- }
+ if (readsize <= 0) {
+ ErrPrint("Available data: %d\n", readsize);
+ ret = -ECONNRESET;
+ break;
+ }
- DbgPrint("Recv returns: %d\n", ret);
- break;
- }
+ chunk = create_chunk(readsize);
+ if (!chunk) {
+ ErrPrint("Failed to create a new chunk: %d\n", readsize);
+ ret = -ENOMEM;
+ break;
+ }
- /* Update chunk size */
- chunk->size = ret;
+ ret = secure_socket_recv(tcb->handle, chunk->data, chunk->size, &chunk->pid, &chunk->fd);
+ if (ret <= 0) {
+ destroy_chunk(chunk);
+ if (ret == -EAGAIN) {
+ DbgPrint("Retry to get data\n");
+ continue;
+ }
- /*!
- * Count of chunk elements are same with PIPE'd data
- */
- if (chunk_append(tcb, chunk) < 0) {
- destroy_chunk(chunk);
- break;
- }
+ DbgPrint("Recv returns: %d\n", ret);
+ break;
}
- DbgPrint("Client CB is terminated (%d)\n", tcb->handle);
- /* Wake up main thread to get disconnected event */
- event_ch = EVENT_TERM;
+ /* Update chunk size */
+ chunk->size = ret;
- if (write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("%d byte is not written\n", sizeof(event_ch));
+ /*!
+ * Count of chunk elements are same with PIPE'd data
+ */
+ if (chunk_append(tcb, chunk) < 0) {
+ destroy_chunk(chunk);
+ break;
}
+ }
+
+ DbgPrint("Client CB is terminated (%d)\n", tcb->handle);
+ /* Wake up main thread to get disconnected event */
+ event_ch = EVENT_TERM;
- return (void *)(unsigned long)ret;
+ if (write_safe(tcb->evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("%d byte is not written\n", sizeof(event_ch));
+ }
+
+ return (void *)(unsigned long)ret;
}
/*!
@@ -443,23 +445,23 @@ static void *client_cb(void *data)
*/
static inline void tcb_destroy(struct tcb *tcb)
{
- int status;
+ int status;
- dlist_remove_data(s_info.tcb_list, tcb);
+ dlist_remove_data(s_info.tcb_list, tcb);
- if (tcb->id > 0) {
- g_source_remove(tcb->id);
- }
+ if (tcb->id > 0) {
+ g_source_remove(tcb->id);
+ }
- CLOSE_PIPE(tcb->evt_pipe);
- CLOSE_PIPE(tcb->ctrl_pipe);
+ CLOSE_PIPE(tcb->evt_pipe);
+ CLOSE_PIPE(tcb->ctrl_pipe);
- status = pthread_mutex_destroy(&tcb->chunk_lock);
- if (status != 0) {
- ErrPrint("Failed to destroy mutex: %s\n", strerror(status));
- }
+ status = pthread_mutex_destroy(&tcb->chunk_lock);
+ if (status != 0) {
+ ErrPrint("Failed to destroy mutex: %s\n", strerror(status));
+ }
- free(tcb);
+ free(tcb);
}
/*!
@@ -468,41 +470,41 @@ static inline void tcb_destroy(struct tcb *tcb)
*/
static gboolean evt_pipe_cb(GIOChannel *src, GIOCondition cond, gpointer data)
{
- int pipe_read;
- struct tcb *tcb = data;
- int ret;
+ int pipe_read;
+ struct tcb *tcb = data;
+ int ret;
- pipe_read = g_io_channel_unix_get_fd(src);
+ pipe_read = g_io_channel_unix_get_fd(src);
- if (tcb->evt_pipe[PIPE_READ] != pipe_read) {
- ErrPrint("Closed handle (%d <> %d)\n", tcb->evt_pipe[PIPE_READ], pipe_read);
- goto errout;
- }
+ if (tcb->evt_pipe[PIPE_READ] != pipe_read) {
+ ErrPrint("Closed handle (%d <> %d)\n", tcb->evt_pipe[PIPE_READ], pipe_read);
+ goto errout;
+ }
- if (!(cond & G_IO_IN)) {
- ErrPrint("PIPE is not valid\n");
- goto errout;
- }
+ if (!(cond & G_IO_IN)) {
+ ErrPrint("PIPE is not valid\n");
+ goto errout;
+ }
- if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
- ErrPrint("PIPE is not valid\n");
- goto errout;
- }
+ if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+ ErrPrint("PIPE is not valid\n");
+ goto errout;
+ }
- ret = tcb->service_cb(tcb->handle, tcb->data);
- if (ret < 0) {
- DbgPrint("Service callback returns %d < 0\n", ret);
- goto errout;
- }
+ ret = tcb->service_cb(tcb->handle, tcb->data);
+ if (ret < 0) {
+ DbgPrint("Service callback returns %d < 0\n", ret);
+ goto errout;
+ }
- return TRUE;
+ return TRUE;
errout:
- DbgPrint("Disconnecting\n");
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
- terminate_thread(tcb);
- tcb_destroy(tcb);
- return FALSE;
+ DbgPrint("Disconnecting\n");
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ terminate_thread(tcb);
+ tcb_destroy(tcb);
+ return FALSE;
}
/*!
@@ -511,54 +513,54 @@ errout:
*/
static inline struct tcb *tcb_create(int client_fd, int is_sync, int (*service_cb)(int fd, void *data), void *data)
{
- struct tcb *tcb;
- int status;
+ struct tcb *tcb;
+ int status;
- tcb = malloc(sizeof(*tcb));
- if (!tcb) {
- ErrPrint("Error: %s\n", strerror(errno));
- return NULL;
- }
+ tcb = malloc(sizeof(*tcb));
+ if (!tcb) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ return NULL;
+ }
- tcb->handle = client_fd;
- tcb->chunk_list = NULL;
- tcb->service_cb = service_cb;
- tcb->data = data;
- tcb->id = 0;
+ tcb->handle = client_fd;
+ tcb->chunk_list = NULL;
+ tcb->service_cb = service_cb;
+ tcb->data = data;
+ tcb->id = 0;
- status = pthread_mutex_init(&tcb->chunk_lock, NULL);
- if (status != 0) {
- ErrPrint("Error: %s\n", strerror(status));
- free(tcb);
- return NULL;
- }
+ status = pthread_mutex_init(&tcb->chunk_lock, NULL);
+ if (status != 0) {
+ ErrPrint("Error: %s\n", strerror(status));
+ free(tcb);
+ return NULL;
+ }
- if (pipe2(tcb->evt_pipe, O_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- status = pthread_mutex_destroy(&tcb->chunk_lock);
- if (status != 0) {
- ErrPrint("Error: %s\n", strerror(status));
- }
- free(tcb);
- return NULL;
+ if (pipe2(tcb->evt_pipe, O_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ status = pthread_mutex_destroy(&tcb->chunk_lock);
+ if (status != 0) {
+ ErrPrint("Error: %s\n", strerror(status));
}
+ free(tcb);
+ return NULL;
+ }
- if (pipe2(tcb->ctrl_pipe, O_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
-
- CLOSE_PIPE(tcb->evt_pipe);
+ if (pipe2(tcb->ctrl_pipe, O_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
- status = pthread_mutex_destroy(&tcb->chunk_lock);
- if (status != 0) {
- ErrPrint("Error: %s\n", strerror(status));
- }
+ CLOSE_PIPE(tcb->evt_pipe);
- free(tcb);
- return NULL;
+ status = pthread_mutex_destroy(&tcb->chunk_lock);
+ if (status != 0) {
+ ErrPrint("Error: %s\n", strerror(status));
}
- DbgPrint("[%d] New TCB created: R(%d), W(%d)\n", client_fd, tcb->evt_pipe[PIPE_READ], tcb->evt_pipe[PIPE_WRITE]);
- return tcb;
+ free(tcb);
+ return NULL;
+ }
+
+ DbgPrint("[%d] New TCB created: R(%d), W(%d)\n", client_fd, tcb->evt_pipe[PIPE_READ], tcb->evt_pipe[PIPE_WRITE]);
+ return tcb;
}
/*!
@@ -567,94 +569,94 @@ static inline struct tcb *tcb_create(int client_fd, int is_sync, int (*service_c
*/
static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
{
- int socket_fd;
- int fd;
- int ret;
- struct tcb *tcb;
- GIOChannel *gio;
- struct server *server = data;
-
- socket_fd = g_io_channel_unix_get_fd(src);
- if (!(cond & G_IO_IN)) {
- ErrPrint("Accept socket closed\n");
- server_destroy(server);
- return FALSE;
- }
-
- if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
- DbgPrint("Socket connection is lost\n");
- server_destroy(server);
- return FALSE;
- }
-
- fd = secure_socket_get_connection_handle(socket_fd);
- if (fd < 0) {
- ErrPrint("Failed to get client fd from socket\n");
- server_destroy(server);
- return FALSE;
- }
+ int socket_fd;
+ int fd;
+ int ret;
+ struct tcb *tcb;
+ GIOChannel *gio;
+ struct server *server = data;
+
+ socket_fd = g_io_channel_unix_get_fd(src);
+ if (!(cond & G_IO_IN)) {
+ ErrPrint("Accept socket closed\n");
+ server_destroy(server);
+ return FALSE;
+ }
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
+ if ((cond & G_IO_ERR) || (cond & G_IO_HUP) || (cond & G_IO_NVAL)) {
+ DbgPrint("Socket connection is lost\n");
+ server_destroy(server);
+ return FALSE;
+ }
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
+ fd = secure_socket_get_connection_handle(socket_fd);
+ if (fd < 0) {
+ ErrPrint("Failed to get client fd from socket\n");
+ server_destroy(server);
+ return FALSE;
+ }
- tcb = tcb_create(fd, 0, server->service_cb, server->data);
- if (!tcb) {
- ErrPrint("Failed to create a TCB\n");
- secure_socket_destroy_handle(fd);
- server_destroy(server);
- return FALSE;
- }
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
- tcb->server_handle = socket_fd;
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
- s_info.tcb_list = dlist_append(s_info.tcb_list, tcb);
+ tcb = tcb_create(fd, 0, server->service_cb, server->data);
+ if (!tcb) {
+ ErrPrint("Failed to create a TCB\n");
+ secure_socket_destroy_handle(fd);
+ server_destroy(server);
+ return FALSE;
+ }
- gio = g_io_channel_unix_new(tcb->evt_pipe[PIPE_READ]);
- if (!gio) {
- ErrPrint("Failed to get gio\n");
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- server_destroy(server);
- return FALSE;
- }
+ tcb->server_handle = socket_fd;
- g_io_channel_set_close_on_unref(gio, FALSE);
+ s_info.tcb_list = dlist_append(s_info.tcb_list, tcb);
- tcb->id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_pipe_cb, tcb);
- if (tcb->id == 0) {
- GError *err = NULL;
- ErrPrint("Failed to add IO Watch\n");
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- server_destroy(server);
- return FALSE;
+ gio = g_io_channel_unix_new(tcb->evt_pipe[PIPE_READ]);
+ if (!gio) {
+ ErrPrint("Failed to get gio\n");
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ server_destroy(server);
+ return FALSE;
+ }
+
+ g_io_channel_set_close_on_unref(gio, FALSE);
+
+ tcb->id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_pipe_cb, tcb);
+ if (tcb->id == 0) {
+ GError *err = NULL;
+ ErrPrint("Failed to add IO Watch\n");
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
g_io_channel_unref(gio);
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ server_destroy(server);
+ return FALSE;
+ }
+ g_io_channel_unref(gio);
- invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
+ invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
- ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
- if (ret != 0) {
- ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- server_destroy(server);
- return FALSE;
- }
+ ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
+ if (ret != 0) {
+ ErrPrint("Thread creation failed: %s\n", strerror(ret));
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ server_destroy(server);
+ return FALSE;
+ }
- return TRUE;
+ return TRUE;
}
/*!
@@ -663,74 +665,74 @@ static gboolean accept_cb(GIOChannel *src, GIOCondition cond, gpointer data)
*/
EAPI int com_core_thread_client_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
{
- GIOChannel *gio;
- int client_fd;
- struct tcb *tcb;
- int ret;
-
- client_fd = secure_socket_create_client(addr);
- if (client_fd < 0) {
- return client_fd;
- }
-
- if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
-
- if (fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- }
-
- tcb = tcb_create(client_fd, is_sync, service_cb, data);
- if (!tcb) {
- ErrPrint("Failed to create a new TCB\n");
- secure_socket_destroy_handle(client_fd);
- return -EFAULT;
- }
-
- tcb->server_handle = -1;
-
- s_info.tcb_list = dlist_append(s_info.tcb_list, tcb);
-
- gio = g_io_channel_unix_new(tcb->evt_pipe[PIPE_READ]);
- if (!gio) {
- ErrPrint("Failed to get gio\n");
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- return -EIO;
- }
-
- g_io_channel_set_close_on_unref(gio, FALSE);
-
- tcb->id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_pipe_cb, tcb);
- if (tcb->id == 0) {
- GError *err = NULL;
- ErrPrint("Failed to add IO Watch\n");
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- return -EIO;
+ GIOChannel *gio;
+ int client_fd;
+ struct tcb *tcb;
+ int ret;
+
+ client_fd = secure_socket_create_client(addr);
+ if (client_fd < 0) {
+ return client_fd;
+ }
+
+ if (fcntl(client_fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+
+ if (fcntl(client_fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+
+ tcb = tcb_create(client_fd, is_sync, service_cb, data);
+ if (!tcb) {
+ ErrPrint("Failed to create a new TCB\n");
+ secure_socket_destroy_handle(client_fd);
+ return -EFAULT;
+ }
+
+ tcb->server_handle = -1;
+
+ s_info.tcb_list = dlist_append(s_info.tcb_list, tcb);
+
+ gio = g_io_channel_unix_new(tcb->evt_pipe[PIPE_READ]);
+ if (!gio) {
+ ErrPrint("Failed to get gio\n");
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ return -EIO;
+ }
+
+ g_io_channel_set_close_on_unref(gio, FALSE);
+
+ tcb->id = g_io_add_watch(gio, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)evt_pipe_cb, tcb);
+ if (tcb->id == 0) {
+ GError *err = NULL;
+ ErrPrint("Failed to add IO Watch\n");
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
-
g_io_channel_unref(gio);
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ return -EIO;
+ }
- invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
+ g_io_channel_unref(gio);
- ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
- if (ret != 0) {
- ErrPrint("Thread creation failed: %s\n", strerror(ret));
- invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
- secure_socket_destroy_handle(tcb->handle);
- tcb_destroy(tcb);
- return -EFAULT;
- }
+ invoke_con_cb_list(tcb->handle, tcb->handle, 0, NULL, 0);
+
+ ret = pthread_create(&tcb->thid, NULL, client_cb, tcb);
+ if (ret != 0) {
+ ErrPrint("Thread creation failed: %s\n", strerror(ret));
+ invoke_disconn_cb_list(tcb->handle, 0, 0, 0);
+ secure_socket_destroy_handle(tcb->handle);
+ tcb_destroy(tcb);
+ return -EFAULT;
+ }
- return tcb->handle;
+ return tcb->handle;
}
/*!
@@ -739,55 +741,55 @@ EAPI int com_core_thread_client_create(const char *addr, int is_sync, int (*serv
*/
EAPI int com_core_thread_server_create(const char *addr, int is_sync, int (*service_cb)(int fd, void *data), void *data)
{
- GIOChannel *gio;
- int fd;
- struct server *server;
-
- fd = secure_socket_create_server(addr);
- if (fd < 0) {
- return fd;
- }
-
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
+ GIOChannel *gio;
+ int fd;
+ struct server *server;
+
+ fd = secure_socket_create_server(addr);
+ if (fd < 0) {
+ return fd;
+ }
+
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ ErrPrint("fcntl: %s\n", strerror(errno));
+ }
+
+ if (!is_sync && fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ ErrPrint("fcntl: %s\n", strerror(errno));
+ }
+
+ server = server_create(fd, service_cb, data);
+ if (!server) {
+ secure_socket_destroy_handle(fd);
+ return -ENOMEM;
+ }
+
+ DbgPrint("Create new IO channel for socket FD: %d\n", fd);
+ gio = g_io_channel_unix_new(server->handle);
+ if (!gio) {
+ ErrPrint("Failed to create new io channel\n");
+ server_destroy(server);
+ return -EIO;
+ }
+
+ g_io_channel_set_close_on_unref(gio, FALSE);
+
+ server->id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc)accept_cb, server);
+ if (server->id == 0) {
+ GError *err = NULL;
+ ErrPrint("Failed to add IO watch\n");
+ g_io_channel_shutdown(gio, TRUE, &err);
+ if (err) {
+ ErrPrint("Shutdown: %s\n", err->message);
+ g_error_free(err);
}
-
- if (!is_sync && fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
-
- server = server_create(fd, service_cb, data);
- if (!server) {
- secure_socket_destroy_handle(fd);
- return -ENOMEM;
- }
-
- DbgPrint("Create new IO channel for socket FD: %d\n", fd);
- gio = g_io_channel_unix_new(server->handle);
- if (!gio) {
- ErrPrint("Failed to create new io channel\n");
- server_destroy(server);
- return -EIO;
- }
-
- g_io_channel_set_close_on_unref(gio, FALSE);
-
- server->id = g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc)accept_cb, server);
- if (server->id == 0) {
- GError *err = NULL;
- ErrPrint("Failed to add IO watch\n");
- g_io_channel_shutdown(gio, TRUE, &err);
- if (err) {
- ErrPrint("Shutdown: %s\n", err->message);
- g_error_free(err);
- }
- g_io_channel_unref(gio);
- server_destroy(server);
- return -EIO;
- }
-
g_io_channel_unref(gio);
- return server->handle;
+ server_destroy(server);
+ return -EIO;
+ }
+
+ g_io_channel_unref(gio);
+ return server->handle;
}
/*!
@@ -796,201 +798,226 @@ EAPI int com_core_thread_server_create(const char *addr, int is_sync, int (*serv
*/
static inline struct tcb *find_tcb_by_handle(int handle)
{
- struct dlist *l;
- struct tcb *tcb;
+ struct dlist *l;
+ struct tcb *tcb;
- dlist_foreach(s_info.tcb_list, l, tcb) {
- if (tcb->handle == handle) {
- return tcb;
- }
+ dlist_foreach(s_info.tcb_list, l, tcb) {
+ if (tcb->handle == handle) {
+ return tcb;
}
+ }
- return NULL;
+ return NULL;
}
-/*!
- * \NOTE
- * Running thread: Main
- */
-EAPI int com_core_thread_send(int handle, const char *buffer, int size, double timeout)
+EAPI int com_core_thread_send_with_fd(int handle, const char *buffer, int size, double timeout, int fd)
{
- int writesize;
- int ret;
- struct tcb *tcb;
+ int writesize;
+ int ret;
+ struct tcb *tcb;
- fd_set set;
+ fd_set set;
- tcb = find_tcb_by_handle(handle);
- if (!tcb) {
- ErrPrint("TCB is not found\n");
- return -EINVAL;
- }
-
- writesize = 0;
- while (size > 0) {
- FD_ZERO(&set);
- FD_SET(tcb->handle, &set);
+ tcb = find_tcb_by_handle(handle);
+ if (!tcb) {
+ ErrPrint("TCB is not found\n");
+ return -EINVAL;
+ }
- if (timeout > 0.0f) {
- struct timeval tv;
+ writesize = 0;
+ while (size > 0) {
+ FD_ZERO(&set);
+ FD_SET(tcb->handle, &set);
- tv.tv_sec = (unsigned long)timeout;
- tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
+ if (timeout > 0.0f) {
+ struct timeval tv;
- ret = select(tcb->handle + 1, NULL, &set, NULL, &tv);
- } else if (timeout == 0.0f) {
- ret = select(tcb->handle + 1, NULL, &set, NULL, NULL);
- } else {
- ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
- return -EINVAL;
- }
+ tv.tv_sec = (unsigned long)timeout;
+ tv.tv_usec = (timeout - (unsigned long)timeout) * 1000000u;
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- DbgPrint("Select receives INTR\n");
- continue;
- }
-
- ErrPrint("Error: %s\n", strerror(errno));
- return ret;
- } else if (ret == 0) {
- ErrPrint("Timeout expired\n");
- break;
- }
+ ret = select(tcb->handle + 1, NULL, &set, NULL, &tv);
+ } else if (timeout == 0.0f) {
+ ret = select(tcb->handle + 1, NULL, &set, NULL, NULL);
+ } else {
+ ErrPrint("Invalid timeout: %lf (it must be greater than 0.0)\n", timeout);
+ return -EINVAL;
+ }
- if (!FD_ISSET(tcb->handle, &set)) {
- ErrPrint("Unexpected handle is toggled\n");
- return -EINVAL;
- }
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EINTR) {
+ DbgPrint("Select receives INTR\n");
+ continue;
+ }
+
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ ErrPrint("Timeout expired\n");
+ break;
+ }
- ret = secure_socket_send(tcb->handle, buffer + writesize, size);
- if (ret < 0) {
- if (ret == -EAGAIN) {
- DbgPrint("Retry to send data (%d:%d)\n", writesize, size);
- continue;
- }
- DbgPrint("Failed to send: %d\n", ret);
- return ret;
- } else if (ret == 0) {
- DbgPrint("Disconnected? : Send bytes: 0\n");
- return 0;
- }
+ if (!FD_ISSET(tcb->handle, &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ return -EINVAL;
+ }
- size -= ret;
- writesize += ret;
+ ret = secure_socket_send(tcb->handle, buffer + writesize, size, fd);
+ if (ret < 0) {
+ if (ret == -EAGAIN) {
+ DbgPrint("Retry to send data (%d:%d)\n", writesize, size);
+ continue;
+ }
+ DbgPrint("Failed to send: %d\n", ret);
+ return ret;
+ } else if (ret == 0) {
+ DbgPrint("Disconnected? : Send bytes: 0\n");
+ return 0;
}
- return writesize;
+ fd = -1; /* Send only once if it is fd */
+ size -= ret;
+ writesize += ret;
+ }
+
+ return writesize;
}
/*!
* \NOTE
* Running thread: Main
*/
-EAPI int com_core_thread_recv(int handle, char *buffer, int size, int *sender_pid, double timeout)
+EAPI int com_core_thread_send(int handle, const char *buffer, int size, double timeout)
{
- int readsize;
- int ret;
- struct chunk *chunk;
- struct dlist *l;
- struct tcb *tcb;
-
- tcb = find_tcb_by_handle(handle);
- if (!tcb) {
- ErrPrint("TCB is not exists\n");
- return -EINVAL;
- }
+ return com_core_thread_send_with_fd(handle, buffer, size, timeout, -1);
+}
- readsize = 0;
- while (readsize < size) {
- l = dlist_nth(tcb->chunk_list, 0);
- chunk = dlist_data(l);
- /*!
- * \note
- * Pumping up the pipe data
- * This is the first time to use a chunk
- */
- if (!chunk) {
- ret = wait_event(tcb, timeout);
- if (ret == -EAGAIN) {
- /* Log is printed from wait_event */
- continue;
- } else if (ret == -ECONNRESET) {
- DbgPrint("Connection is lost\n");
- break;
- } else if (ret < 0) {
- /* Log is printed from wait_event */
- return ret;
- }
-
- l = dlist_nth(tcb->chunk_list, 0);
- chunk = dlist_data(l);
- if (!chunk) {
- char event_ch;
-
- /* Consuming the event */
- if (read(tcb->evt_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("Failed to get readsize: %s\n", strerror(errno));
- } else if (event_ch == EVENT_READY) {
- ErrPrint("Failed to get a new chunk\n");
- } else if (event_ch == EVENT_TERM) {
- DbgPrint("Disconnected\n");
- }
-
- break;
- }
+EAPI int com_core_thread_recv_with_fd(int handle, char *buffer, int size, int *sender_pid, double timeout, int *fd)
+{
+ int readsize;
+ int ret;
+ struct chunk *chunk;
+ struct dlist *l;
+ struct tcb *tcb;
+ int _sender_pid;
+ int _fd;
+
+ tcb = find_tcb_by_handle(handle);
+ if (!tcb) {
+ ErrPrint("TCB is not exists\n");
+ return -EINVAL;
+ }
+
+ if (!sender_pid) {
+ sender_pid = &_sender_pid;
+ }
+
+ if (!fd) {
+ fd = &_fd;
+ }
+
+ *fd = -1;
+ readsize = 0;
+ while (readsize < size) {
+ l = dlist_nth(tcb->chunk_list, 0);
+ chunk = dlist_data(l);
+ /*!
+ * \note
+ * Pumping up the pipe data
+ * This is the first time to use a chunk
+ */
+ if (!chunk) {
+ ret = wait_event(tcb, timeout);
+ if (ret == -EAGAIN) {
+ /* Log is printed from wait_event */
+ continue;
+ } else if (ret == -ECONNRESET) {
+ DbgPrint("Connection is lost\n");
+ break;
+ } else if (ret < 0) {
+ /* Log is printed from wait_event */
+ return ret;
+ }
+
+ l = dlist_nth(tcb->chunk_list, 0);
+ chunk = dlist_data(l);
+ if (!chunk) {
+ char event_ch;
+
+ /* Consuming the event */
+ if (read(tcb->evt_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("Failed to get readsize: %s\n", strerror(errno));
+ } else if (event_ch == EVENT_READY) {
+ ErrPrint("Failed to get a new chunk\n");
+ } else if (event_ch == EVENT_TERM) {
+ DbgPrint("Disconnected\n");
}
- ret = chunk->size - chunk->offset;
- ret = ret > (size - readsize) ? (size - readsize) : ret;
- memcpy(buffer + readsize, chunk->data + chunk->offset, ret);
- readsize += ret;
- chunk->offset += ret;
+ break;
+ }
+ }
- *sender_pid = chunk->pid;
+ ret = chunk->size - chunk->offset;
+ ret = ret > (size - readsize) ? (size - readsize) : ret;
+ memcpy(buffer + readsize, chunk->data + chunk->offset, ret);
+ readsize += ret;
+ chunk->offset += ret;
- if (chunk->offset == chunk->size) {
- chunk_remove(tcb, chunk);
- }
+ *sender_pid = chunk->pid;
+ if (chunk->fd >= 0) {
+ *fd = chunk->fd;
+ }
+
+ if (chunk->offset == chunk->size) {
+ chunk_remove(tcb, chunk);
}
+ }
- return readsize;
+ return readsize;
}
/*!
* \NOTE
* Running thread: Main
*/
-EAPI int com_core_thread_server_destroy(int handle)
+EAPI int com_core_thread_recv(int handle, char *buffer, int size, int *sender_pid, double timeout)
{
- struct dlist *l;
- struct dlist *n;
- struct tcb *tcb;
- struct server *server;
-
- dlist_foreach_safe(s_info.tcb_list, l, n, tcb) {
- if (tcb->server_handle != handle) {
- continue;
- }
+ return com_core_thread_recv_with_fd(handle, buffer, size, sender_pid, timeout, NULL);
+}
- invoke_disconn_cb_list(handle, 0, 0, 0);
- terminate_thread(tcb);
- tcb_destroy(tcb);
- return 0;
+/*!
+ * \NOTE
+ * Running thread: Main
+ */
+EAPI int com_core_thread_server_destroy(int handle)
+{
+ struct dlist *l;
+ struct dlist *n;
+ struct tcb *tcb;
+ struct server *server;
+
+ dlist_foreach_safe(s_info.tcb_list, l, n, tcb) {
+ if (tcb->server_handle != handle) {
+ continue;
}
- dlist_foreach_safe(s_info.server_list, l, n, server) {
- if (server->handle != handle) {
- continue;
- }
+ invoke_disconn_cb_list(handle, 0, 0, 0);
+ terminate_thread(tcb);
+ tcb_destroy(tcb);
+ return 0;
+ }
- invoke_disconn_cb_list(handle, 0, 0, 0);
- server_destroy(server);
- return 0;
+ dlist_foreach_safe(s_info.server_list, l, n, server) {
+ if (server->handle != handle) {
+ continue;
}
- return -ENOENT;
+ invoke_disconn_cb_list(handle, 0, 0, 0);
+ server_destroy(server);
+ return 0;
+ }
+
+ return -ENOENT;
}
/*!
@@ -999,17 +1026,17 @@ EAPI int com_core_thread_server_destroy(int handle)
*/
EAPI int com_core_thread_client_destroy(int handle)
{
- struct tcb *tcb;
+ struct tcb *tcb;
- tcb = find_tcb_by_handle(handle);
- if (!tcb) {
- return -ENOENT;
- }
+ tcb = find_tcb_by_handle(handle);
+ if (!tcb) {
+ return -ENOENT;
+ }
- invoke_disconn_cb_list(handle, 0, 0, 0);
- terminate_thread(tcb);
- tcb_destroy(tcb);
- return 0;
+ invoke_disconn_cb_list(handle, 0, 0, 0);
+ terminate_thread(tcb);
+ tcb_destroy(tcb);
+ return 0;
}
/* End of a file */
diff --git a/src/secure_socket.c b/src/secure_socket.c
index c6252df..a1f69eb 100644
--- a/src/secure_socket.c
+++ b/src/secure_socket.c
@@ -42,482 +42,507 @@
#define RCVBUF_SZ 524288 /*!< 512 KB, this will be doubled by kernel */
enum scheme {
- SCHEME_LOCAL = 0x00,
- SCHEME_REMOTE = 0x01,
- SCHEME_UNKNOWN = 0x02,
+ SCHEME_LOCAL = 0x00,
+ SCHEME_REMOTE = 0x01,
+ SCHEME_UNKNOWN = 0x02,
};
struct function_table {
- int type;
- int (*create_socket)(const char *peer, int port, struct sockaddr *addr);
- int (*setup_handle)(int handle);
+ int type;
+ int (*create_socket)(const char *peer, int port, struct sockaddr *addr);
+ int (*setup_handle)(int handle);
};
int errno;
static inline int create_unix_socket(const char *peer, int port, struct sockaddr *addr)
{
- int len;
- int handle;
- struct sockaddr_un *un_addr = (struct sockaddr_un *)addr;
-
- len = sizeof(*un_addr);
- bzero(un_addr, len);
-
- if (strlen(peer) >= sizeof(un_addr->sun_path)) {
- ErrPrint("peer %s is too long to remember it\\n", peer);
- return -1;
- }
-
- /* We can believe this has no prob, because
- * we already check the size of add.rsun_path
- */
- strcpy(un_addr->sun_path, peer);
- un_addr->sun_family = AF_UNIX;
-
- handle = socket(PF_UNIX, SOCK_STREAM, 0);
- if (handle < 0) {
- handle = -errno;
- ErrPrint("Failed to create a socket %s\n", strerror(errno));
- }
-
- return handle;
+ int len;
+ int handle;
+ struct sockaddr_un *un_addr = (struct sockaddr_un *)addr;
+
+ len = sizeof(*un_addr);
+ bzero(un_addr, len);
+
+ if (strlen(peer) >= sizeof(un_addr->sun_path)) {
+ ErrPrint("peer %s is too long to remember it\\n", peer);
+ return -1;
+ }
+
+ /* We can believe this has no prob, because
+ * we already check the size of add.rsun_path
+ */
+ strcpy(un_addr->sun_path, peer);
+ un_addr->sun_family = AF_UNIX;
+
+ handle = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (handle < 0) {
+ handle = -errno;
+ ErrPrint("Failed to create a socket %s\n", strerror(errno));
+ }
+
+ return handle;
}
static inline int create_inet_socket(const char *peer, int port, struct sockaddr *addr)
{
- int handle;
- struct sockaddr_in *in_addr = (struct sockaddr_in *)addr;
-
- bzero(in_addr, sizeof(*in_addr));
-
- in_addr->sin_port = htons(port);
- in_addr->sin_family = AF_INET;
- if (*peer == '\0') {
- in_addr->sin_addr.s_addr = htonl(INADDR_ANY);
- } else {
- in_addr->sin_addr.s_addr = inet_addr(peer);
- }
-
- handle = socket(AF_INET, SOCK_STREAM, 0);
- if (handle < 0) {
- handle = -errno;
- ErrPrint("socket: %s\n", strerror(errno));
- }
-
- return handle;
+ int handle;
+ struct sockaddr_in *in_addr = (struct sockaddr_in *)addr;
+
+ bzero(in_addr, sizeof(*in_addr));
+
+ in_addr->sin_port = htons(port);
+ in_addr->sin_family = AF_INET;
+ if (*peer == '\0') {
+ in_addr->sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ in_addr->sin_addr.s_addr = inet_addr(peer);
+ }
+
+ handle = socket(AF_INET, SOCK_STREAM, 0);
+ if (handle < 0) {
+ handle = -errno;
+ ErrPrint("socket: %s\n", strerror(errno));
+ }
+
+ return handle;
}
static inline int create_systemd_socket(const char *peer, int port, struct sockaddr *addr)
{
- int handle = -1;
- int cnt;
-
- cnt = sd_listen_fds(0);
- if (cnt > 1) {
- ErrPrint("To many file descriptors are received on socket activation: %d\n", cnt);
- } else if (cnt == 1) {
- handle = SD_LISTEN_FDS_START + 0;
- } else {
- handle = create_inet_socket(peer, port, addr);
- }
-
- return handle;
+ int handle = -1;
+ int cnt;
+
+ cnt = sd_listen_fds(0);
+ if (cnt > 1) {
+ ErrPrint("To many file descriptors are received on socket activation: %d\n", cnt);
+ } else if (cnt == 1) {
+ handle = SD_LISTEN_FDS_START + 0;
+ } else {
+ handle = create_inet_socket(peer, port, addr);
+ }
+
+ return handle;
}
static inline int setup_unix_handle(int handle)
{
- int on = 1;
- int sndbuf = SNDBUF_SZ;
- int rcvbuf = RCVBUF_SZ;
-
- if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
- int ret;
- ret = -errno;
- ErrPrint("Failed to change sock opt : %s\n", strerror(errno));
- return ret;
- }
+ int on = 1;
+ int sndbuf = SNDBUF_SZ;
+ int rcvbuf = RCVBUF_SZ;
- (void)setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
- (void)setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
- (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
+ if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
+ int ret;
+ ret = -errno;
+ ErrPrint("Failed to change sock opt : %s\n", strerror(errno));
+ return ret;
+ }
- return 0;
+ (void)setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
+ (void)setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+ (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
+
+ return 0;
}
static inline int setup_inet_handle(int handle)
{
- int on = 1;
+ int on = 1;
- (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
+ (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
- return 0;
+ return 0;
}
static inline char *parse_scheme(const char *peer, int *port, struct function_table *vtable)
{
- int _port;
- char *addr = NULL;
-
- if (!port)
- port = &_port;
-
- *port = 0;
-
- if (!strncasecmp(peer, COM_CORE_LOCAL_SCHEME, COM_CORE_LOCAL_SCHEME_LEN)) {
- vtable->type = (int)SCHEME_LOCAL;
- peer += COM_CORE_LOCAL_SCHEME_LEN;
-
- addr = strdup(peer);
- if (!addr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- }
-
- vtable->create_socket = create_unix_socket;
- vtable->setup_handle = setup_unix_handle;
- } else if (!strncasecmp(peer, COM_CORE_SD_LOCAL_SCHEME, COM_CORE_SD_LOCAL_SCHEME_LEN)) {
- vtable->type = (int)SCHEME_LOCAL;
- peer += COM_CORE_SD_LOCAL_SCHEME_LEN;
-
- addr = strdup(peer);
- if (!addr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- }
-
- vtable->create_socket = create_systemd_socket;
- vtable->setup_handle = setup_unix_handle;
- } else if (!strncasecmp(peer, COM_CORE_REMOTE_SCHEME, COM_CORE_REMOTE_SCHEME_LEN)) {
- register int len;
- char *endptr;
-
- vtable->type = (int)SCHEME_REMOTE;
- peer += COM_CORE_REMOTE_SCHEME_LEN;
-
- for (len = 0; peer[len] && peer[len] != ':'; len++);
- if (peer[len] != ':') {
- ErrPrint("Invalid syntax: %s\n", peer);
- goto out;
- }
-
- addr = malloc(len + 1);
- if (!addr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- goto out;
- }
-
- if (len > 0) {
- strncpy(addr, peer, len);
- }
-
- addr[len] = '\0';
-
- peer += len + 1;
- *port = strtoul(peer, &endptr, 10);
- if (*endptr != '\0' || peer == endptr) {
- ErrPrint("Invalid: %s[%d]\n", peer - len - 1, len + 1);
- free(addr);
- addr = NULL;
- goto out;
- }
-
- vtable->create_socket = create_inet_socket;
- vtable->setup_handle = setup_inet_handle;
- } else {
- /* Fallback to local scheme */
- vtable->type = (int)SCHEME_LOCAL;
- addr = strdup(peer);
- if (!addr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- goto out;
- }
-
- vtable->create_socket = create_unix_socket;
- vtable->setup_handle = setup_unix_handle;
- }
+ int _port;
+ char *addr = NULL;
-out:
- return addr;
-}
+ if (!port)
+ port = &_port;
-EAPI int secure_socket_create_client(const char *peer)
-{
- int port;
- char *addr;
- int ret;
- struct function_table vtable;
- struct sockaddr *sockaddr;
- struct sockaddr_in in_addr;
- struct sockaddr_un un_addr;
- int handle;
- int addrlen;
-
- addr = parse_scheme(peer, &port, &vtable);
+ *port = 0;
+
+ if (!strncasecmp(peer, COM_CORE_LOCAL_SCHEME, COM_CORE_LOCAL_SCHEME_LEN)) {
+ vtable->type = (int)SCHEME_LOCAL;
+ peer += COM_CORE_LOCAL_SCHEME_LEN;
+
+ addr = strdup(peer);
if (!addr) {
- ErrPrint("peer: [%s] is not valid\n", peer);
- return -EINVAL;
+ ErrPrint("Heap: %s\n", strerror(errno));
}
- switch (vtable.type) {
- case SCHEME_LOCAL:
- sockaddr = (struct sockaddr *)&un_addr;
- addrlen = sizeof(un_addr);
- break;
- case SCHEME_REMOTE:
- sockaddr = (struct sockaddr *)&in_addr;
- addrlen = sizeof(in_addr);
- break;
- default:
- free(addr);
- return -EINVAL;
- }
+ vtable->create_socket = create_unix_socket;
+ vtable->setup_handle = setup_unix_handle;
+ } else if (!strncasecmp(peer, COM_CORE_SD_LOCAL_SCHEME, COM_CORE_SD_LOCAL_SCHEME_LEN)) {
+ vtable->type = (int)SCHEME_LOCAL;
+ peer += COM_CORE_SD_LOCAL_SCHEME_LEN;
- handle = vtable.create_socket(addr, port, sockaddr);
- free(addr);
- if (handle < 0) {
- return handle;
+ addr = strdup(peer);
+ if (!addr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
}
- ret = connect(handle, sockaddr, addrlen);
- if (ret < 0) {
- ret = -errno;
- ErrPrint("Failed to connect to server [%s] %s\n",
- peer, strerror(errno));
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
-
- return ret;
+ vtable->create_socket = create_systemd_socket;
+ vtable->setup_handle = setup_unix_handle;
+ } else if (!strncasecmp(peer, COM_CORE_REMOTE_SCHEME, COM_CORE_REMOTE_SCHEME_LEN)) {
+ register int len;
+ char *endptr;
+
+ vtable->type = (int)SCHEME_REMOTE;
+ peer += COM_CORE_REMOTE_SCHEME_LEN;
+
+ for (len = 0; peer[len] && peer[len] != ':'; len++);
+ if (peer[len] != ':') {
+ ErrPrint("Invalid syntax: %s\n", peer);
+ goto out;
}
- ret = vtable.setup_handle(handle);
- if (ret < 0) {
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
+ addr = malloc(len + 1);
+ if (!addr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ goto out;
+ }
- return ret;
+ if (len > 0) {
+ strncpy(addr, peer, len);
}
- return handle;
-}
+ addr[len] = '\0';
-EAPI int secure_socket_create_server(const char *peer)
-{
- int port;
- char *addr;
- int handle;
- int ret;
- struct sockaddr *sockaddr;
- struct sockaddr_in in_addr;
- struct sockaddr_un un_addr;
- struct function_table vtable;
- int addrlen;
+ peer += len + 1;
+ *port = strtoul(peer, &endptr, 10);
+ if (*endptr != '\0' || peer == endptr) {
+ ErrPrint("Invalid: %s[%d]\n", peer - len - 1, len + 1);
+ free(addr);
+ addr = NULL;
+ goto out;
+ }
- addr = parse_scheme(peer, &port, &vtable);
+ vtable->create_socket = create_inet_socket;
+ vtable->setup_handle = setup_inet_handle;
+ } else {
+ /* Fallback to local scheme */
+ vtable->type = (int)SCHEME_LOCAL;
+ addr = strdup(peer);
if (!addr) {
- ErrPrint("Failed to parse scheme\n");
- return -EINVAL;
+ ErrPrint("Heap: %s\n", strerror(errno));
+ goto out;
}
- switch (vtable.type) {
+ vtable->create_socket = create_unix_socket;
+ vtable->setup_handle = setup_unix_handle;
+ }
+
+out:
+ return addr;
+}
+
+EAPI int secure_socket_create_client(const char *peer)
+{
+ int port;
+ char *addr;
+ int ret;
+ struct function_table vtable;
+ struct sockaddr *sockaddr;
+ struct sockaddr_in in_addr;
+ struct sockaddr_un un_addr;
+ int handle;
+ int addrlen;
+
+ addr = parse_scheme(peer, &port, &vtable);
+ if (!addr) {
+ ErrPrint("peer: [%s] is not valid\n", peer);
+ return -EINVAL;
+ }
+
+ switch (vtable.type) {
case SCHEME_LOCAL:
- sockaddr = (struct sockaddr *)&un_addr;
- addrlen = sizeof(un_addr);
- break;
+ sockaddr = (struct sockaddr *)&un_addr;
+ addrlen = sizeof(un_addr);
+ break;
case SCHEME_REMOTE:
- sockaddr = (struct sockaddr *)&in_addr;
- addrlen = sizeof(in_addr);
- break;
+ sockaddr = (struct sockaddr *)&in_addr;
+ addrlen = sizeof(in_addr);
+ break;
default:
- free(addr);
- return -EINVAL;
- }
+ free(addr);
+ return -EINVAL;
+ }
- handle = vtable.create_socket(addr, port, sockaddr);
- free(addr);
- if (handle < 0) {
- return handle;
- }
+ handle = vtable.create_socket(addr, port, sockaddr);
+ free(addr);
+ if (handle < 0) {
+ return handle;
+ }
- ret = bind(handle, sockaddr, addrlen);
- if (ret < 0) {
- ret = -errno;
- ErrPrint("bind: %s\n", strerror(errno));
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
- return ret;
+ ret = connect(handle, sockaddr, addrlen);
+ if (ret < 0) {
+ ret = -errno;
+ ErrPrint("Failed to connect to server [%s] %s\n",
+ peer, strerror(errno));
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
}
- ret = listen(handle, BACKLOG);
- if (ret < 0) {
- ret = -errno;
- ErrPrint("listen: %s\n", strerror(errno));
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
- return ret;
- }
+ return ret;
+ }
- if (vtable.type == SCHEME_LOCAL) {
- if (chmod(peer, 0666) < 0) {
- ErrPrint("Failed to change the permission of a socket (%s)\n", strerror(errno));
- }
+ ret = vtable.setup_handle(handle);
+ if (ret < 0) {
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
}
- return handle;
+ return ret;
+ }
+
+ return handle;
}
-EAPI int secure_socket_get_connection_handle(int server_handle)
+EAPI int secure_socket_create_server(const char *peer)
{
- struct sockaddr_in in_addr;
- struct sockaddr_un un_addr;
- struct sockaddr *addr;
- int handle;
- int ret;
- socklen_t size = sizeof(un_addr);
-
- /* Finding the largest buffer */
- if (sizeof(in_addr) > sizeof(un_addr)) {
- addr = (struct sockaddr *)&in_addr;
- size = sizeof(in_addr);
- } else {
- addr = (struct sockaddr *)&un_addr;
- size = sizeof(un_addr);
+ int port;
+ char *addr;
+ int handle;
+ int ret;
+ struct sockaddr *sockaddr;
+ struct sockaddr_in in_addr;
+ struct sockaddr_un un_addr;
+ struct function_table vtable;
+ int addrlen;
+
+ addr = parse_scheme(peer, &port, &vtable);
+ if (!addr) {
+ ErrPrint("Failed to parse scheme\n");
+ return -EINVAL;
+ }
+
+ switch (vtable.type) {
+ case SCHEME_LOCAL:
+ sockaddr = (struct sockaddr *)&un_addr;
+ addrlen = sizeof(un_addr);
+ break;
+ case SCHEME_REMOTE:
+ sockaddr = (struct sockaddr *)&in_addr;
+ addrlen = sizeof(in_addr);
+ break;
+ default:
+ free(addr);
+ return -EINVAL;
+ }
+
+ handle = vtable.create_socket(addr, port, sockaddr);
+ free(addr);
+ if (handle < 0) {
+ return handle;
+ }
+
+ ret = bind(handle, sockaddr, addrlen);
+ if (ret < 0) {
+ ret = -errno;
+ ErrPrint("bind: %s\n", strerror(errno));
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
}
+ return ret;
+ }
- handle = accept(server_handle, addr, &size);
- if (handle < 0) {
- ret = -errno;
- ErrPrint("Failed to accept a new client %s\n", strerror(errno));
- return ret;
+ ret = listen(handle, BACKLOG);
+ if (ret < 0) {
+ ret = -errno;
+ ErrPrint("listen: %s\n", strerror(errno));
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
}
+ return ret;
+ }
- if (addr->sa_family == AF_UNIX) {
- ret = setup_unix_handle(handle);
- if (ret < 0) {
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
-
- handle = ret;
- }
- } else if (addr->sa_family == AF_INET) {
- ret = setup_inet_handle(handle);
- if (ret < 0) {
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
-
- handle = ret;
- }
- } else {
- ErrPrint("Unknown address family: %d\n", addr->sa_family);
+ if (vtable.type == SCHEME_LOCAL) {
+ if (chmod(peer, 0666) < 0) {
+ ErrPrint("Failed to change the permission of a socket (%s)\n", strerror(errno));
}
+ }
- return handle;
+ return handle;
}
-EAPI int secure_socket_send(int handle, const char *buffer, int size)
+EAPI int secure_socket_get_connection_handle(int server_handle)
{
- struct msghdr msg;
- struct iovec iov;
- int ret;
+ struct sockaddr_in in_addr;
+ struct sockaddr_un un_addr;
+ struct sockaddr *addr;
+ int handle;
+ int ret;
+ socklen_t size = sizeof(un_addr);
+
+ /* Finding the largest buffer */
+ if (sizeof(in_addr) > sizeof(un_addr)) {
+ addr = (struct sockaddr *)&in_addr;
+ size = sizeof(in_addr);
+ } else {
+ addr = (struct sockaddr *)&un_addr;
+ size = sizeof(un_addr);
+ }
+
+ handle = accept(server_handle, addr, &size);
+ if (handle < 0) {
+ ret = -errno;
+ ErrPrint("Failed to accept a new client %s\n", strerror(errno));
+ return ret;
+ }
+
+ if (addr->sa_family == AF_UNIX) {
+ ret = setup_unix_handle(handle);
+ if (ret < 0) {
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
+ }
- if (!buffer || size <= 0) {
- ErrPrint("Reject: 0 byte data sending\n");
- return -EINVAL;
+ handle = ret;
}
-
- memset(&msg, 0, sizeof(msg));
- iov.iov_base = (char *)buffer;
- iov.iov_len = size;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- ret = sendmsg(handle, &msg, 0);
+ } else if (addr->sa_family == AF_INET) {
+ ret = setup_inet_handle(handle);
if (ret < 0) {
- ret = -errno;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
- return -EAGAIN;
- }
- ErrPrint("Failed to send message [%s]\n", strerror(errno));
- return ret;
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
+ }
+
+ handle = ret;
}
+ } else {
+ ErrPrint("Unknown address family: %d\n", addr->sa_family);
+ }
- return iov.iov_len;
+ return handle;
}
-EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid)
+EAPI int secure_socket_send(int handle, const char *buffer, int size, int fd)
{
- struct msghdr msg;
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct cmsghdr hdr;
+ char control[CMSG_SPACE(sizeof(int))];
+ } cmsgu;
+ int ret;
+
+ if (!buffer || size <= 0) {
+ ErrPrint("Reject: 0 byte data sending\n");
+ return -EINVAL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ iov.iov_base = (char *)buffer;
+ iov.iov_len = size;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (fd >= 0) {
struct cmsghdr *cmsg;
- struct iovec iov;
- char control[1024];
- int _pid;
- int ret;
-
- if (size <= 0 || !buffer) {
- return -EINVAL;
- }
+ int *cdata;
- if (!sender_pid) {
- sender_pid = &_pid;
- }
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
- memset(&msg, 0, sizeof(msg));
- iov.iov_base = buffer;
- iov.iov_len = size;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = control;
- msg.msg_controllen = sizeof(control);
-
- ret = recvmsg(handle, &msg, 0);
- if (ret == 0) {
- /*!< Disconnected */
- DbgPrint("Disconnected\n");
- return 0;
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cdata = (int *)CMSG_DATA(cmsg);
+ *cdata = fd;
+ }
+
+ ret = sendmsg(handle, &msg, 0);
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+ return -EAGAIN;
}
+ ErrPrint("Failed to send message [%s]\n", strerror(errno));
+ return ret;
+ }
- if (ret < 0) {
- ret = -errno;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
- return -EAGAIN;
- }
-
- ErrPrint("Failed to recvmsg [%s]\n", strerror(errno));
- return ret;
- }
+ return iov.iov_len;
+}
- *sender_pid = -1; /* In case of remote socket, cannot delivery this */
- cmsg = CMSG_FIRSTHDR(&msg);
- while (cmsg) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
- struct ucred *cred;
+EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid, int *fd)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char control[1024];
+ int _pid;
+ int ret;
+
+ if (size <= 0 || !buffer) {
+ return -EINVAL;
+ }
+
+ if (!sender_pid) {
+ sender_pid = &_pid;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ iov.iov_base = buffer;
+ iov.iov_len = size;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = control;
+ msg.msg_controllen = sizeof(control);
+
+ ret = recvmsg(handle, &msg, 0);
+ if (ret == 0) {
+ /*!< Disconnected */
+ DbgPrint("Disconnected\n");
+ return 0;
+ }
- cred = (struct ucred *)CMSG_DATA(cmsg);
- *sender_pid = cred->pid;
- }
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+ return -EAGAIN;
+ }
- cmsg = CMSG_NXTHDR(&msg, cmsg);
+ ErrPrint("Failed to recvmsg [%s]\n", strerror(errno));
+ return ret;
+ }
+
+ *sender_pid = -1; /* In case of remote socket, cannot delivery this */
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while (cmsg) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
+ struct ucred *cred;
+
+ cred = (struct ucred *)CMSG_DATA(cmsg);
+ *sender_pid = cred->pid;
+ } else if (fd && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ int *cdata;
+ cdata = (int *)CMSG_DATA(cmsg);
+ *fd = *cdata;
}
- return iov.iov_len;
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+
+ return iov.iov_len;
}
EAPI int secure_socket_destroy_handle(int handle)
{
- if (close(handle) < 0) {
- int ret;
- ret = -errno;
- ErrPrint("close: %s\n", strerror(errno));
- return ret;
- }
+ if (close(handle) < 0) {
+ int ret;
+ ret = -errno;
+ ErrPrint("close: %s\n", strerror(errno));
+ return ret;
+ }
- return 0;
+ return 0;
}
#undef _GNU_SOURCE