#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
-#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
#include <glib.h>
};
struct cbdata {
- int (*service_cb)(int fd, int readsize, void *data);
+ int (*service_cb)(int fd, void *data);
void *data;
};
int client_fd;
struct cbdata *cbdata = data;
int ret;
- int readsize;
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);
- secure_socket_remove_connection_handle(client_fd);
+ 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);
- secure_socket_remove_connection_handle(client_fd);
- return FALSE;
- }
-
- if (ioctl(client_fd, FIONREAD, &readsize) < 0 || readsize == 0) {
- DbgPrint("Client is disconencted (fd: %d, readsize: %d)\n", client_fd, readsize);
- invoke_disconn_cb_list(client_fd);
- secure_socket_remove_connection_handle(client_fd);
+ secure_socket_destroy_handle(client_fd);
return FALSE;
}
- ret = cbdata->service_cb(client_fd, readsize, cbdata->data);
+ ret = cbdata->service_cb(client_fd, cbdata->data);
if (ret < 0) {
- DbgPrint("service callback returns < 0\n");
+ DbgPrint("service callback returns %d < 0\n", ret);
invoke_disconn_cb_list(client_fd);
- secure_socket_remove_connection_handle(client_fd);
+ secure_socket_destroy_handle(client_fd);
return FALSE;
}
gio = g_io_channel_unix_new(client_fd);
if (!gio) {
ErrPrint("Failed to get gio\n");
- secure_socket_remove_connection_handle(client_fd);
+ secure_socket_destroy_handle(client_fd);
free(cbdata);
return FALSE;
}
g_error_free(err);
}
g_io_channel_unref(gio);
- secure_socket_remove_connection_handle(client_fd);
+ secure_socket_destroy_handle(client_fd);
free(cbdata);
return FALSE;
}
return TRUE;
}
-EAPI int com_core_server_create(const char *addr, int is_sync, int (*service_cb)(int fd, int readsize, void *data), void *data)
+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;
return fd;
}
-EAPI int com_core_client_create(const char *addr, int is_sync, int (*service_cb)(int fd, int readsize, void *data), void *data)
+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;
return 0;
}
+EAPI int com_core_recv(int handle, char *buffer, int size, int *sender_pid, double timeout)
+{
+ int readsize;
+ int ret;
+
+ readsize = 0;
+ while (size > 0) {
+ if (timeout > 0.0f) {
+ struct timeval tv;
+ fd_set set;
+
+ 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);
+ if (ret < 0) {
+ /*!< Error */
+ ret = -errno;
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ /*!< Timeout */
+ ErrPrint("Timeout expired\n");
+ return -ETIMEDOUT;
+ }
+
+ if (!FD_ISSET(handle, &set)) {
+ ErrPrint("Unexpected handle is toggled\n");
+ 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;
+ }
+ return ret;
+ } else if (ret == 0) {
+ return 0;
+ }
+
+ size -= ret;
+ readsize += ret;
+ }
+
+ return readsize;
+}
+
+EAPI int com_core_send(int handle, const char *buffer, int size, double timeout)
+{
+ int writesize;
+ int ret;
+
+ writesize = 0;
+ while (size > 0) {
+ if (timeout > 0.0f) {
+ struct timeval tv;
+ fd_set set;
+
+ 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, NULL, &set, NULL, &tv);
+ if (ret < 0) {
+ ret = -errno;
+ ErrPrint("Error: %s\n", strerror(errno));
+ return ret;
+ } else if (ret == 0) {
+ ErrPrint("Timeout expired\n");
+ return -ETIMEDOUT;
+ }
+
+ 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 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;
EAPI int com_core_server_destroy(int handle)
{
- if (close(handle) < 0)
- ErrPrint("Close error[%d]: %s\n", handle, strerror(errno));
+ DbgPrint("Close server handle[%d]\n", handle);
+ secure_socket_destroy_handle(handle);
return 0;
}
EAPI int com_core_client_destroy(int handle)
{
- if (close(handle) < 0)
- ErrPrint("Close error[%d]: %s\n", handle, strerror(errno));
+ DbgPrint("Close client handle[%d]\n", handle);
+ secure_socket_destroy_handle(handle);
return 0;
}
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <glib.h>
#include <dlog.h>
#include "com-core_packet.h"
#include "util.h"
-#define DEFAULT_TIMEOUT 2
+#define DEFAULT_TIMEOUT 2.0f
static struct info {
struct dlist *recv_list;
struct packet *packet;
int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data);
void *data;
-
- guint timeout;
};
struct recv_ctx {
int offset;
pid_t pid;
struct packet *packet;
+ double timeout;
};
-static inline struct request_ctx *find_request_ctx(int handle, unsigned long seq)
+static inline struct request_ctx *find_request_ctx(int handle, double seq)
{
struct request_ctx *ctx;
struct dlist *l;
static inline void destroy_request_ctx(struct request_ctx *ctx)
{
- if (ctx->timeout > 0)
- g_source_remove(ctx->timeout);
-
packet_unref(ctx->packet);
dlist_remove_data(s_info.request_list, ctx);
free(ctx);
free(ctx);
}
-static inline struct recv_ctx *create_recv_ctx(int handle)
+static inline struct recv_ctx *create_recv_ctx(int handle, double timeout)
{
struct recv_ctx *ctx;
ctx->packet = NULL;
ctx->handle = handle;
ctx->pid = (pid_t)-1;
+ ctx->timeout = timeout;
s_info.recv_list = dlist_append(s_info.recv_list, ctx);
return ctx;
}
-static inline void packet_ready(int handle, const struct recv_ctx *receive, struct method *table)
+static inline int packet_ready(int handle, const struct recv_ctx *receive, struct method *table)
{
struct request_ctx *request;
- unsigned long sequence;
+ double sequence;
struct packet *result;
register int i;
+ int ret;
+
+ ret = 0;
- /*!
- * \note
- * Is this ack packet?
- */
switch (packet_type(receive->packet)) {
case PACKET_ACK:
sequence = packet_seq(receive->packet);
result = table[i].handler(receive->pid, handle, receive->packet);
if (result) {
- int ret;
- ret = secure_socket_send(handle, (void *)packet_data(result), packet_size(result));
- if (ret < 0)
+ ret = com_core_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;
}
- return;
+ /*!
+ * Return negative value will make call the disconnected_cb
+ */
+ return ret;
}
static int client_disconnected_cb(int handle, void *data)
struct dlist *n;
pid_t pid = (pid_t)-1;
- DbgPrint("Clean up all requests and a receive context\n");
-
receive = find_recv_ctx(handle);
if (receive) {
pid = receive->pid;
destroy_recv_ctx(receive);
}
+ DbgPrint("Clean up all requests and a receive context for handle(%d) for pid(%d)\n", handle, pid);
+
dlist_foreach_safe(s_info.request_list, l, n, request) {
- if (request->handle == handle) {
- if (request->recv_cb)
- request->recv_cb(pid, handle, NULL, request->data);
+ if (request->handle != handle)
+ continue;
- destroy_request_ctx(request);
- }
+ if (request->recv_cb)
+ request->recv_cb(pid, handle, NULL, request->data);
+
+ destroy_request_ctx(request);
}
return 0;
}
-static int service_cb(int handle, int readsize, void *data)
+static int service_cb(int handle, void *data)
{
struct recv_ctx *receive;
pid_t pid;
receive = find_recv_ctx(handle);
if (!receive)
- receive = create_recv_ctx(handle);
+ receive = create_recv_ctx(handle, DEFAULT_TIMEOUT);
if (!receive) {
ErrPrint("Couldn't find or create a receive context\n");
return -EIO;
}
- while (readsize > 0) {
- switch (receive->state) {
- case RECV_STATE_INIT:
- 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));
- destroy_recv_ctx(receive);
- return -ENOMEM;
- }
+ switch (receive->state) {
+ case RECV_STATE_INIT:
+ 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;
+ }
- ret = secure_socket_recv(handle, ptr, size, &pid);
- if (ret < 0 || (receive->pid != -1 && receive->pid != pid)) {
+ ret = com_core_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);
- destroy_recv_ctx(receive);
- return -EIO;
+ return -EIO; /*!< Return negative value will invoke the client_disconnected_cb */
}
receive->pid = pid;
if (!receive->packet) {
ErrPrint("Built packet is not valid\n");
- destroy_recv_ctx(receive);
- return -EFAULT;
+ return -EFAULT; /*!< Return negative value will invoke the client_disconnected_cb */
}
receive->offset += ret;
- readsize -= 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;
+ }
+ break;
+ case RECV_STATE_BODY:
+ size = packet_size(receive->packet) - receive->offset;
+ if (size == 0) {
+ receive->state = RECV_STATE_READY;
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));
- destroy_recv_ctx(receive);
- return -ENOMEM;
- }
+ }
+ /*!
+ * \note
+ * Getting body
+ */
+ ptr = malloc(size);
+ if (!ptr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
- ret = secure_socket_recv(handle, ptr, size, &pid);
- if (ret < 0 || receive->pid != pid) {
+ ret = com_core_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);
- destroy_recv_ctx(receive);
return -EIO;
}
free(ptr);
if (!receive->packet) {
- destroy_recv_ctx(receive);
+ ErrPrint("Built packet is not valid\n");
return -EFAULT;
}
receive->offset += ret;
- readsize -= ret;
+
if (receive->offset == packet_size(receive->packet))
receive->state = RECV_STATE_READY;
- break;
- case RECV_STATE_READY:
- default:
- break;
+ } else {
+ DbgPrint("ZERO bytes receives(%d)\n", pid);
+ free(ptr);
+ return -ECONNRESET;
}
- if (receive->state == RECV_STATE_READY) {
- packet_ready(handle, receive, data);
- destroy_recv_ctx(receive);
- /*!
- * \note
- * Just quit from this function
- * Even if we have read size
- * Next time is comming soon ;)
- */
- break;
- }
+ break;
+ case RECV_STATE_READY:
+ default:
+ break;
}
- return 0;
-}
-
-static gboolean timeout_cb(gpointer data)
-{
- struct request_ctx *ctx = data;
-
- ErrPrint("Timeout (Not responding in time)\n");
-
- if (ctx->recv_cb)
- ctx->recv_cb(ctx->pid, ctx->handle, NULL, ctx->data);
+ if (receive->state == RECV_STATE_READY) {
+ ret = packet_ready(handle, receive, data);
+ if (ret == 0)
+ destroy_recv_ctx(receive);
+ /*!
+ * if ret is negative value, disconnected_cb will be called after this function
+ */
+ } else {
+ ret = 0;
+ }
- ctx->timeout = 0u;
- destroy_request_ctx(ctx);
- return FALSE;
+ return ret;
}
-EAPI int com_core_packet_async_send(int handle, struct packet *packet, unsigned int timeout, int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data), void *data)
+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 (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);
- if (timeout > 0) {
- ctx->timeout = g_timeout_add(timeout, timeout_cb, ctx);
- if (ctx->timeout == 0)
- ErrPrint("Failed to add timeout\n");
- }
- ret = secure_socket_send(handle, (void *)packet_data(packet), packet_size(packet));
+ ret = com_core_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);
{
int ret;
- ret = secure_socket_send(handle, (void *)packet_data(packet), packet_size(packet));
- if (ret != packet_size(packet))
+ if (packet_type(packet) != PACKET_REQ_NOACK) {
+ ErrPrint("Invalid type - should be PACKET_REQ_NOACK\n");
+ return -EINVAL;
+ }
+
+ ret = com_core_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;
}
-EAPI struct packet *com_core_packet_oneshot_send(const char *addr, struct packet *packet)
+EAPI struct packet *com_core_packet_oneshot_send(const char *addr, struct packet *packet, double timeout)
{
int ret;
- int sz;
int fd;
pid_t pid;
int offset;
struct packet *result = NULL;
void *ptr;
- struct timeval timeout;
- fd_set set;
fd = secure_socket_create_client(addr);
if (fd < 0)
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
ErrPrint("Error: %s\n", strerror(errno));
- ret = secure_socket_send(fd, (char *)packet_data(packet), packet_size(packet));
- if (ret < 0) {
- secure_socket_destroy(fd);
- return NULL;
- }
- DbgPrint("Sent: %d bytes (%d bytes)\n", ret, packet_size(packet));
-
- FD_ZERO(&set);
- FD_SET(fd, &set);
-
- timeout.tv_sec = DEFAULT_TIMEOUT;
- timeout.tv_usec = 0;
-
- ret = select(fd + 1, &set, NULL, NULL, &timeout);
- if (ret < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- secure_socket_destroy(fd);
- return NULL;
- } else if (ret != 1) {
- ErrPrint("Timeout (%d)\n", ret);
- secure_socket_destroy(fd);
- return NULL;
- }
-
- if (!FD_ISSET(fd, &set)) {
- ErrPrint("Invalid handle\n");
- secure_socket_destroy(fd);
- return NULL;
- }
-
- if (ioctl(fd, FIONREAD, &sz) < 0 || sz == 0) {
- ErrPrint("Connection closed\n");
- secure_socket_destroy(fd);
- return NULL;
- }
+ ret = com_core_send(fd, (char *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
+ if (ret < 0)
+ goto out;
- DbgPrint("Readable size: %d\n", sz);
- if (sz < packet_header_size()) {
- ErrPrint("Invalid packet [SIZE: %d]\n", sz);
- secure_socket_destroy(fd);
- return NULL;
- }
+ DbgPrint("Sent: %d bytes (%d bytes)\n", ret, packet_size(packet));
- offset = 0;
ptr = malloc(packet_header_size());
if (!ptr) {
ErrPrint("Heap: %s\n", strerror(errno));
- secure_socket_destroy(fd);
- return NULL;
+ goto out;
}
- ret = secure_socket_recv(fd, (char *)ptr, packet_header_size(), &pid);
- if (ret < 0) {
+ offset = 0;
+ ret = com_core_recv(fd, (char *)ptr, packet_header_size(), &pid, timeout);
+ if (ret <= 0) {
+ DbgPrint("Recv returns %s\n", ret);
free(ptr);
- secure_socket_destroy(fd);
- return NULL;
+ 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;
+ }
}
- DbgPrint("Recv'd size: %d (header: %d)\n", ret, packet_header_size());
- result = packet_build(result, offset, ptr, ret);
- offset += ret;
- free(ptr);
DbgPrint("Payload size: %d\n", packet_payload_size(result));
- if (sz < packet_payload_size(result) + packet_header_size()) {
- ErrPrint("Invalid packet [%d <> %d]\n", sz, packet_payload_size(result) + packet_header_size());
- secure_socket_destroy(fd);
- packet_destroy(result);
- return NULL;
- }
ptr = malloc(packet_payload_size(result));
if (!ptr) {
ErrPrint("Heap: %s\n", strerror(errno));
- secure_socket_destroy(fd);
packet_destroy(result);
- return NULL;
+ result = NULL;
+ goto out;
}
- ret = secure_socket_recv(fd, (char *)ptr, packet_payload_size(result), &pid);
- if (ret < 0) {
+ ret = com_core_recv(fd, (char *)ptr, packet_payload_size(result), &pid, timeout);
+ if (ret <= 0) {
+ DbgPrint("Recv returns %s\n", ret);
free(ptr);
- secure_socket_destroy(fd);
packet_destroy(result);
- return NULL;
+ result = NULL;
+ } else {
+ DbgPrint("Recv'd %d bytes (pid: %d)\n", ret, pid);
+ result = packet_build(result, offset, ptr, ret);
+ offset += ret;
+ free(ptr);
}
- result = packet_build(result, offset, ptr, ret);
- offset += ret;
- free(ptr);
- secure_socket_destroy(fd);
+out:
+ secure_socket_destroy_handle(fd);
DbgPrint("Close connection: %d\n", fd);
return result;
}