From 3779f9292fbfe263331478b837067bccbeb91fb4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 7 Oct 2009 21:49:24 +0200 Subject: [PATCH] Bugfix: IPC: Correctly handle the case when multiple messages get received at once via the socket When the sending application was so fast (*cough*) that the messages could get queued by the kernel, it may happen that we receive multiple messages at once. --- src/ipc.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/ipc.c b/src/ipc.c index 34675943..0bef2ea2 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -77,10 +77,16 @@ static void ipc_handle_message(uint8_t *message, int size, LOG("payload as a string = %s\n", message); switch (message_type) { - case I3_IPC_MESSAGE_TYPE_COMMAND: - parse_command(global_conn, (const char*)message); + case I3_IPC_MESSAGE_TYPE_COMMAND: { + /* To get a properly terminated buffer, we copy + * message_size bytes out of the buffer */ + char *command = scalloc(message_size); + strncpy(command, (const char*)message, message_size); + parse_command(global_conn, (const char*)command); + free(command); break; + } default: LOG("unhandled ipc message\n"); break; @@ -148,20 +154,30 @@ static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) { } uint8_t *message = (uint8_t*)buf; - message += strlen(I3_IPC_MAGIC); - n -= strlen(I3_IPC_MAGIC); + while (n > 0) { + LOG("IPC: n = %d\n", n); + message += strlen(I3_IPC_MAGIC); + n -= strlen(I3_IPC_MAGIC); - /* The next 32 bit after the magic are the message size */ - uint32_t message_size = *((uint32_t*)message); - message += sizeof(uint32_t); - n -= sizeof(uint32_t); + /* The next 32 bit after the magic are the message size */ + uint32_t message_size = *((uint32_t*)message); + message += sizeof(uint32_t); + n -= sizeof(uint32_t); - /* The last 32 bits of the header are the message type */ - uint32_t message_type = *((uint32_t*)message); - message += sizeof(uint32_t); - n -= sizeof(uint32_t); + if (message_size > n) { + LOG("IPC: Either the message size was wrong or the message was not read completely, dropping\n"); + return; + } - ipc_handle_message(message, n, message_size, message_type); + /* The last 32 bits of the header are the message type */ + uint32_t message_type = *((uint32_t*)message); + message += sizeof(uint32_t); + n -= sizeof(uint32_t); + + ipc_handle_message(message, n, message_size, message_type); + n -= message_size; + message += message_size; + } } /*