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"); }