From 77120450ffdfa3e94c5f49275d6893c417c7e61e Mon Sep 17 00:00:00 2001
From: Philippe PITTOLI
Date: Fri, 12 Oct 2018 01:59:56 +0200
Subject: [PATCH] GOING 4-BYTE LENGTH, YEAH \o/
---
core/error.h | 2 +-
core/message.c | 30 ++++-----
core/message.h | 2 +-
core/usocket.c | 141 ++++++++++++++++++++++++-------------------
core/usocket.h | 3 +
pong/app/ipc-debug.c | 68 ++++++++++++++++++---
pong/app/pongd.c | 4 +-
7 files changed, 162 insertions(+), 88 deletions(-)
diff --git a/core/error.h b/core/error.h
index c4bf76e..dcbb98d 100644
--- a/core/error.h
+++ b/core/error.h
@@ -6,7 +6,7 @@
#define IPC_ERROR_NOT_ENOUGH_MEMORY 100
#define IPC_ERROR_WRONG_PARAMETERS 101
-// #define IPC_WITH_ERRORS 2
+// #define IPC_WITH_ERRORS 3
#ifdef IPC_WITH_ERRORS
#define handle_error(msg) \
diff --git a/core/message.c b/core/message.c
index 06f096d..089fe0d 100644
--- a/core/message.c
+++ b/core/message.c
@@ -16,26 +16,26 @@ int ipc_message_format_read (struct ipc_message *m, const char *buf, ssize_t msi
{
assert (m != NULL);
assert (buf != NULL);
- assert (msize <= BUFSIZ - 3);
+ assert (msize <= IPC_MAX_MESSAGE_SIZE);
if (m == NULL)
return -1;
m->type = buf[0];
- memcpy (&m->length, buf+1, 2);
+ memcpy (&m->length, buf+1, sizeof m->length);
- assert (m->length <= BUFSIZ - 3);
+ assert (m->length <= IPC_MAX_MESSAGE_SIZE);
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
- printf ("type %d : msize = %ld, length = %d\n", m->type, msize, m->length);
+ printf ("type %d, paylen = %u, total = %lu\n", m->type, m->length, msize);
#endif
- assert (m->length == msize - 3 || m->length == 0);
+ assert (m->length == msize - IPC_HEADER_SIZE || m->length == 0);
if (m->payload != NULL)
free (m->payload), m->payload = NULL;
if (m->payload == NULL && m->length > 0) {
m->payload = malloc (m->length);
- memcpy (m->payload, buf+3, m->length);
+ memcpy (m->payload, buf+IPC_HEADER_SIZE, m->length);
}
return 0;
@@ -46,7 +46,7 @@ int ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *
assert (m != NULL);
assert (buf != NULL);
assert (msize != NULL);
- assert (m->length <= BUFSIZ -3);
+ assert (m->length <= IPC_MAX_MESSAGE_SIZE);
if (m == NULL)
return -1;
@@ -58,19 +58,19 @@ int ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *
return -3;
if (*buf == NULL) {
- *buf = malloc (3 + m->length);
- memset (*buf, 0, 3 + m->length);
+ *buf = malloc (IPC_HEADER_SIZE + m->length);
+ memset (*buf, 0, IPC_HEADER_SIZE + m->length);
}
char *buffer = *buf;
buffer[0] = m->type;
- memcpy (buffer + 1, &m->length, 2);
+ memcpy (buffer + 1, &m->length, sizeof m->length);
if (m->payload != NULL) {
- memcpy (buffer + 3, m->payload, m->length);
+ memcpy (buffer + IPC_HEADER_SIZE, m->payload, m->length);
}
- *msize = 3 + m->length;
+ *msize = IPC_HEADER_SIZE + m->length;
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
printf ("sending msg: type %u, size %d, msize %ld\n", m->type, m->length, *msize);
@@ -85,7 +85,7 @@ int ipc_message_read (int fd, struct ipc_message *m)
assert (m != NULL);
char *buf = NULL;
- ssize_t msize = BUFSIZ;
+ ssize_t msize = IPC_MAX_MESSAGE_SIZE;
int ret = usock_recv (fd, &buf, &msize);
if (ret < 0) {
@@ -143,10 +143,10 @@ int ipc_message_write (int fd, const struct ipc_message *m)
int ipc_message_format (struct ipc_message *m, char type, const char *payload, ssize_t length)
{
assert (m != NULL);
- assert (length + 3 <= BUFSIZ);
+ assert (length <= IPC_MAX_MESSAGE_SIZE);
assert ((length == 0 && payload == NULL) || (length > 0 && payload != NULL));
- if (length + 3 > BUFSIZ) {
+ if (length > IPC_MAX_MESSAGE_SIZE) {
handle_err ("msg_format_con", "msgsize > BUFSIZ");
return -1;
}
diff --git a/core/message.h b/core/message.h
index 68651cc..5f6216a 100644
--- a/core/message.h
+++ b/core/message.h
@@ -16,7 +16,7 @@ enum msg_types {
struct ipc_message {
char type;
- unsigned short length;
+ unsigned int length;
char *payload;
};
diff --git a/core/usocket.c b/core/usocket.c
index 8b7bc65..1e20c27 100644
--- a/core/usocket.c
+++ b/core/usocket.c
@@ -20,6 +20,7 @@ int usock_send (const int fd, const char *buf, ssize_t len, ssize_t *sent)
return 0;
}
+// *len is changed to the total message size read (header + payload)
int usock_recv (const int fd, char **buf, ssize_t *len)
{
assert(buf != NULL);
@@ -39,75 +40,89 @@ int usock_recv (const int fd, char **buf, ssize_t *len)
if (*buf == NULL) {
// do not allocate too much memory
- if (*len > BUFSIZ) {
- handle_err ("usock_recv", "len > BUFSIZ");
+ if (*len > IPC_MAX_MESSAGE_SIZE) {
+ handle_err ("usock_recv", "len > IPC_MAX_MESSAGE_SIZE");
+ *len = IPC_MAX_MESSAGE_SIZE;
}
- if (*len == 0)
- *len = BUFSIZ;
- *buf = malloc ((*len < BUFSIZ) ? *len : BUFSIZ);
+ *buf = malloc (*len + IPC_HEADER_SIZE);
}
- ret = recv (fd, *buf, *len, 0);
- if (ret < 0) {
- if (*buf != NULL)
- free (*buf);
+ unsigned int msize = 0;
+ unsigned int msize_read = 0;
- handle_err ("usock_recv", "recv ret < 0");
- perror("recv");
- *len = 0;
-
- switch (ret) {
-
- // The receive buffer pointer(s) point outside the process's address space.
- case EFAULT:
- handle_err ("usock_recv", "critical error: use of unallocated memory, quitting...");
- exit (1);
-
- // Invalid argument passed.
- case EINVAL:
- handle_err ("usock_recv", "critical error: invalid arguments to read(2), quitting...");
- exit (1);
-
- // Could not allocate memory for recvmsg().
- case ENOMEM:
- handle_err ("usock_recv", "critical error: cannot allocate memory, quitting...");
- exit (1);
-
- // The argument sockfd is an invalid descriptor.
- case EBADF:
- handle_err ("usock_recv", "critical error: invalid descriptor, quitting...");
- exit (1);
-
- // The file descriptor sockfd does not refer to a socket.
- case ENOTSOCK:
- handle_err ("usock_recv", "critical error: fd is not a socket, quitting...");
- exit (1);
-
- // The socket is associated with a connection-oriented protocol and has not
- // been connected (see connect(2) and accept(2)).
- case ENOTCONN:
- handle_err ("usock_recv", "critical error: read(2) on a non connected socket, quitting...");
- exit (1);
-
- // EWOULDBLOCK
- case EAGAIN:
-
- // A remote host refused to allow the network connection
- // (typically because it is not running the requested service).
- case ECONNREFUSED:
-
- // The receive was interrupted by delivery of a signal before
- // any data were available; see signal(7).
- case EINTR:
-
- default:
- handle_err ("usock_recv", "unsupported error");
- ;
+ do {
+ ret = recv (fd, *buf, *len, 0);
+ if (msize == 0) {
+ memcpy (&msize, *buf + 1, sizeof msize);
}
- return -1;
- }
+ assert (msize < IPC_MAX_MESSAGE_SIZE);
+ msize_read += ret - IPC_HEADER_SIZE;
- *len = ret;
+ if (ret < 0) {
+ if (*buf != NULL)
+ free (*buf);
+
+ handle_err ("usock_recv", "recv ret < 0");
+ perror("recv");
+ *len = 0;
+
+ switch (ret) {
+
+ // The receive buffer pointer(s) point outside the process's address space.
+ case EFAULT:
+ handle_err ("usock_recv", "critical error: use of unallocated memory, quitting...");
+ exit (1);
+
+ // Invalid argument passed.
+ case EINVAL:
+ handle_err ("usock_recv", "critical error: invalid arguments to read(2), quitting...");
+ exit (1);
+
+ // Could not allocate memory for recvmsg().
+ case ENOMEM:
+ handle_err ("usock_recv", "critical error: cannot allocate memory, quitting...");
+ exit (1);
+
+ // The argument sockfd is an invalid descriptor.
+ case EBADF:
+ handle_err ("usock_recv", "critical error: invalid descriptor, quitting...");
+ exit (1);
+
+ // The file descriptor sockfd does not refer to a socket.
+ case ENOTSOCK:
+ handle_err ("usock_recv", "critical error: fd is not a socket, quitting...");
+ exit (1);
+
+ // The socket is associated with a connection-oriented protocol and has not
+ // been connected (see connect(2) and accept(2)).
+ case ENOTCONN:
+ handle_err ("usock_recv", "critical error: read(2) on a non connected socket, quitting...");
+ exit (1);
+
+ // EWOULDBLOCK
+ case EAGAIN:
+
+ // A remote host refused to allow the network connection
+ // (typically because it is not running the requested service).
+ case ECONNREFUSED:
+
+ // The receive was interrupted by delivery of a signal before
+ // any data were available; see signal(7).
+ case EINTR:
+
+ default:
+ handle_err ("usock_recv", "unsupported error");
+ ;
+ }
+ return -1;
+ }
+
+#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
+ printf ("fragmentation: message size read %u, should read %u\n", msize_read, msize);
+#endif
+ } while (msize > msize_read);
+
+ *len = msize + IPC_HEADER_SIZE;
// 1 on none byte received, indicates a closed recipient
if (ret == 0) {
diff --git a/core/usocket.h b/core/usocket.h
index 49fe891..3a803e3 100644
--- a/core/usocket.h
+++ b/core/usocket.h
@@ -10,6 +10,9 @@
#define TMPDIR "/run/ipc/"
#define PATH_MAX 4096
+#define IPC_HEADER_SIZE 5
+#define IPC_MAX_MESSAGE_SIZE 8000000-IPC_HEADER_SIZE
+
struct ipc_service {
unsigned int version;
unsigned int index;
diff --git a/pong/app/ipc-debug.c b/pong/app/ipc-debug.c
index 682ae0e..800ecf0 100644
--- a/pong/app/ipc-debug.c
+++ b/pong/app/ipc-debug.c
@@ -10,6 +10,8 @@
#define SERVICE_NAME "pongd"
+#define MAX_MESSAGE_SIZE 20000
+
void interactive (char * service_name, char *env[])
{
struct ipc_message m;
@@ -30,16 +32,24 @@ void interactive (char * service_name, char *env[])
char msg_type = 0;
while (1) {
+#if 0 // version with readline, slow, valgrind-incompatible
+
char * mtype_str = readline("msg type: ");
- sscanf(mtype_str, "%c", &msg_type);
+ if (strlen(mtype_str) == 0 || strncmp (mtype_str, "exit", 4) == 0) {
+ free (mtype_str);
+ break;
+ }
+ msg_type = atoi(mtype_str);
free(mtype_str);
char * buf = readline ("msg: ");
- if (strlen(buf) == 0 || strncmp (buf, "exit", 4) == 0)
+ if (strlen(buf) == 0 || strncmp (buf, "exit", 4) == 0) {
+ free (buf);
break;
+ }
ipc_message_format (&m, msg_type, buf, strlen(buf));
- memset (buf, 0, BUFSIZ);
+ free (buf);
// print_msg (&m);
@@ -54,27 +64,71 @@ void interactive (char * service_name, char *env[])
exit (EXIT_FAILURE);
}
- printf ("msg recv: %s", m.payload);
+ printf ("\nmsg recv: %s", m.payload);
ipc_message_empty (&m);
+#else
+
+ char mtype_str[50];
+ memset(mtype_str, 0, 50);
+ printf ("message type: ");
+ fflush(stdout);
+ read(0, mtype_str, 50);
+ msg_type = atoi(mtype_str);
+ memset(mtype_str, 0, 50);
+
+ char mpayload[MAX_MESSAGE_SIZE];
+ memset(mpayload, 0, MAX_MESSAGE_SIZE);
+ printf ("message payload: ");
+ fflush(stdout);
+ read(0, mpayload, MAX_MESSAGE_SIZE);
+ if (strlen(mpayload) == 0 || strncmp (mpayload, "exit", 4) == 0) {
+ break;
+ }
+
+ ipc_message_format (&m, msg_type, mpayload, strlen(mpayload));
+ // print_msg (&m);
+
+ if (ipc_application_write (&srv, &m) < 0) {
+ handle_err("main", "application_write < 0");
+ exit (EXIT_FAILURE);
+ }
+ ipc_message_empty (&m);
+
+ if (msg_type == 0) { // message type 0 => close the server, no read to do
+ break;
+ }
+
+ if (ipc_application_read (&srv, &m) < 0) {
+ handle_err("main", "application_read < 0");
+ exit (EXIT_FAILURE);
+ }
+
+ if (m.length > 0) {
+ printf ("msg recv: %.*s", m.length, m.payload);
+ }
+ ipc_message_empty (&m);
+#endif
}
if (ipc_application_close (&srv) < 0) {
handle_err("main", "application_close < 0");
exit (EXIT_FAILURE);
}
+ ipc_message_empty (&m);
}
int main (int argc, char *argv[], char *env[])
{
- argc = argc; // warnings
- argv = argv; // warnings
-
char service_name[100];
+ memset (service_name, 0, 100);
if (argc != 1) {
ssize_t t = strlen(argv[1]) > 100 ? 100 : strlen(argv[1]);
memcpy(service_name, argv[1], t);
}
+ else {
+ memcpy(service_name, SERVICE_NAME, strlen(SERVICE_NAME));
+ }
interactive (service_name, env);
diff --git a/pong/app/pongd.c b/pong/app/pongd.c
index b03d46d..97312a5 100644
--- a/pong/app/pongd.c
+++ b/pong/app/pongd.c
@@ -91,7 +91,9 @@ void handle_new_msg (struct ipc_clients *clients, struct ipc_clients *clients_ta
exit (0);
}
- printf ("new message : %s", m.payload);
+ if (m.length > 0) {
+ printf ("new message : %.*s", m.length, m.payload);
+ }
if (ipc_server_write (pc, &m) < 0) {
handle_err( "handle_new_msg", "server_write < 0");
}