2019-06-03 21:25:59 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2019-06-12 15:02:43 +02:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
2018-10-09 13:20:26 +02:00
|
|
|
#include "message.h"
|
2016-12-21 01:26:47 +01:00
|
|
|
#include "usocket.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
2019-06-12 15:02:43 +02:00
|
|
|
#define IPC_WITH_ERRORS 3
|
|
|
|
|
2018-10-03 22:02:37 +02:00
|
|
|
void ipc_message_print (const struct ipc_message *m)
|
2016-12-21 02:56:52 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
2018-10-10 23:18:15 +02:00
|
|
|
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
|
2018-10-04 01:54:12 +02:00
|
|
|
printf ("msg: type %d len %d\n", m->type, m->length);
|
2018-10-10 23:18:15 +02:00
|
|
|
#endif
|
2016-12-21 02:56:52 +01:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
|
|
enum ipc_errors ipc_message_new (struct ipc_message **m, ssize_t paylen)
|
|
|
|
{
|
|
|
|
m = malloc (sizeof(struct ipc_message));
|
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_NEW__NO_MESSAGE_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset (*m, 0, sizeof (struct ipc_message));
|
|
|
|
|
|
|
|
if (paylen != 0) {
|
|
|
|
((struct ipc_message *)m)->payload = malloc (paylen);
|
|
|
|
if (((struct ipc_message *)m)->payload == NULL) {
|
|
|
|
free (*m);
|
|
|
|
return IPC_ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IPC_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum ipc_errors ipc_message_format_read (struct ipc_message *m, const char *buf, ssize_t msize)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
|
|
|
assert (buf != NULL);
|
2018-10-12 01:59:56 +02:00
|
|
|
assert (msize <= IPC_MAX_MESSAGE_SIZE);
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_MESSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buf == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_READ__EMPTY_BUFFER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msize > IPC_MAX_MESSAGE_SIZE) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_READ__MESSAGE_SIZE;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-04 01:35:33 +02:00
|
|
|
// message format:
|
|
|
|
// Type (1 B) | Length (4 B) | UserType (1 B) | Payload (Length B)
|
2016-12-21 01:26:47 +01:00
|
|
|
m->type = buf[0];
|
2019-06-12 15:02:43 +02:00
|
|
|
size_t unformated_size = 0;
|
|
|
|
memcpy (&unformated_size, buf+1, sizeof(size_t));
|
|
|
|
m->length = ntohl (unformated_size);
|
2019-06-04 01:35:33 +02:00
|
|
|
m->user_type = buf[1 + sizeof m->length];
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-12 01:59:56 +02:00
|
|
|
assert (m->length <= IPC_MAX_MESSAGE_SIZE);
|
2018-10-10 23:18:15 +02:00
|
|
|
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
|
2019-06-12 15:02:43 +02:00
|
|
|
printf ("receiving msg:\ttype %d, paylen %u, total %lu\n", m->type, m->length, msize);
|
2018-10-10 23:18:15 +02:00
|
|
|
#endif
|
2018-10-12 01:59:56 +02:00
|
|
|
assert (m->length == msize - IPC_HEADER_SIZE || m->length == 0);
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-30 13:18:53 +01:00
|
|
|
if (m->payload != NULL) {
|
|
|
|
free (m->payload);
|
|
|
|
m->payload = NULL;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-30 13:18:53 +01:00
|
|
|
if (m->length > 0) {
|
2018-10-04 01:54:12 +02:00
|
|
|
m->payload = malloc (m->length);
|
2018-10-12 01:59:56 +02:00
|
|
|
memcpy (m->payload, buf+IPC_HEADER_SIZE, m->length);
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
2019-06-12 15:02:43 +02:00
|
|
|
else {
|
|
|
|
m->payload = malloc (1);
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_NONE;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *msize)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
|
|
|
assert (buf != NULL);
|
|
|
|
assert (msize != NULL);
|
2018-10-12 01:59:56 +02:00
|
|
|
assert (m->length <= IPC_MAX_MESSAGE_SIZE);
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MESSAGE;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (buf == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_BUFFER;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (msize == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT_WRITE__EMPTY_MSIZE;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2016-12-21 02:56:52 +01:00
|
|
|
if (*buf == NULL) {
|
2018-10-12 01:59:56 +02:00
|
|
|
*buf = malloc (IPC_HEADER_SIZE + m->length);
|
|
|
|
memset (*buf, 0, IPC_HEADER_SIZE + m->length);
|
2016-12-21 02:56:52 +01:00
|
|
|
}
|
|
|
|
|
2016-12-21 01:26:47 +01:00
|
|
|
char *buffer = *buf;
|
2019-06-12 15:02:43 +02:00
|
|
|
uint32_t paylen = htonl(m->length);
|
2016-12-21 01:26:47 +01:00
|
|
|
|
|
|
|
buffer[0] = m->type;
|
2019-06-12 15:02:43 +02:00
|
|
|
uint32_t net_paylen = htonl(m->length);
|
|
|
|
memcpy (buffer + 1, &net_paylen, sizeof(uint32_t));
|
2019-06-04 01:35:33 +02:00
|
|
|
buffer[1 + sizeof m->length] = m->user_type;
|
2019-06-12 15:02:43 +02:00
|
|
|
if (m->payload != NULL && m->length > 0) {
|
2018-10-12 01:59:56 +02:00
|
|
|
memcpy (buffer + IPC_HEADER_SIZE, m->payload, m->length);
|
2018-10-04 22:51:31 +02:00
|
|
|
}
|
2016-12-21 02:56:52 +01:00
|
|
|
|
2018-10-12 01:59:56 +02:00
|
|
|
*msize = IPC_HEADER_SIZE + m->length;
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-10 23:18:15 +02:00
|
|
|
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
|
2019-06-12 15:02:43 +02:00
|
|
|
printf ("sending msg:\ttype %u, paylen %u, msize %lu\n", m->type, m->length, *msize);
|
2018-10-10 23:18:15 +02:00
|
|
|
#endif
|
2018-10-04 22:51:31 +02:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_NONE;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
// IPC_ERROR_CLOSED_RECIPIENT on closed recipient
|
|
|
|
enum ipc_errors ipc_message_read (int32_t fd, struct ipc_message *m)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_READ__NO_MESSAGE_PARAM;
|
|
|
|
}
|
|
|
|
|
2016-12-21 01:26:47 +01:00
|
|
|
char *buf = NULL;
|
2018-10-12 01:59:56 +02:00
|
|
|
ssize_t msize = IPC_MAX_MESSAGE_SIZE;
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ret = usock_recv (fd, &buf, &msize);
|
|
|
|
if (ret != IPC_ERROR_NONE && ret != IPC_ERROR_CLOSED_RECIPIENT) {
|
2016-12-21 01:26:47 +01:00
|
|
|
handle_err ("msg_read", "usock_recv");
|
2019-06-03 21:25:59 +02:00
|
|
|
return ret;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
// closed recipient, buffer already freed
|
2019-06-03 21:25:59 +02:00
|
|
|
if (ret == IPC_ERROR_CLOSED_RECIPIENT) {
|
|
|
|
return IPC_ERROR_CLOSED_RECIPIENT;
|
2018-10-08 15:18:56 +02:00
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-12 15:02:43 +02:00
|
|
|
if (buf != NULL) {
|
|
|
|
ret = ipc_message_format_read (m, buf, msize);
|
|
|
|
free (buf);
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
return ret; // propagates ipc_message_format return
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ipc_message_write (int32_t fd, const struct ipc_message *m)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_WRITE__NO_MESSAGE_PARAM;
|
|
|
|
}
|
|
|
|
|
2016-12-21 01:26:47 +01:00
|
|
|
char *buf = NULL;
|
2018-10-08 15:18:56 +02:00
|
|
|
ssize_t msize = 0;
|
2018-10-03 21:52:11 +02:00
|
|
|
ipc_message_format_write (m, &buf, &msize);
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
ssize_t nbytes_sent = 0;
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ret = usock_send (fd, buf, msize, &nbytes_sent);
|
|
|
|
if (buf != NULL) {
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret != IPC_ERROR_NONE) {
|
|
|
|
handle_err ("msg_write", "usock_send");
|
|
|
|
return ret;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2018-10-08 15:18:56 +02:00
|
|
|
// what was sent != what should have been sent
|
|
|
|
if (nbytes_sent != msize) {
|
|
|
|
handle_err ("msg_write", "usock_send did not send enough data");
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_MESSAGE_WRITE__NOT_ENOUGH_DATA;
|
2018-10-30 13:18:53 +01:00
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_NONE;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// MSG FORMAT
|
|
|
|
|
2019-06-04 01:35:33 +02:00
|
|
|
enum ipc_errors ipc_message_format (struct ipc_message *m
|
|
|
|
, char type, char utype, const char *payload, ssize_t length)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
2018-10-12 01:59:56 +02:00
|
|
|
assert (length <= IPC_MAX_MESSAGE_SIZE);
|
2018-10-04 01:54:12 +02:00
|
|
|
assert ((length == 0 && payload == NULL) || (length > 0 && payload != NULL));
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT__NO_MESSAGE_PARAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((length == 0 && payload != NULL) || (length > 0 && payload == NULL)) {
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT__INCONSISTENT_PARAMS;
|
|
|
|
}
|
|
|
|
|
2018-10-12 01:59:56 +02:00
|
|
|
if (length > IPC_MAX_MESSAGE_SIZE) {
|
2016-12-21 01:26:47 +01:00
|
|
|
handle_err ("msg_format_con", "msgsize > BUFSIZ");
|
2019-06-03 21:25:59 +02:00
|
|
|
printf ("msg to format: %ld B)\n", length);
|
|
|
|
return IPC_ERROR_MESSAGE_FORMAT__LENGTH;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
m->type = type;
|
2019-06-04 01:35:33 +02:00
|
|
|
m->user_type = utype;
|
2018-11-02 21:03:54 +01:00
|
|
|
m->length = (uint32_t) length;
|
2016-12-21 02:56:52 +01:00
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
if (payload != NULL) {
|
|
|
|
if (m->payload != NULL) {
|
|
|
|
free (m->payload);
|
|
|
|
}
|
2018-10-08 15:18:56 +02:00
|
|
|
|
2018-10-04 01:54:12 +02:00
|
|
|
m->payload = malloc (length);
|
2018-10-08 15:18:56 +02:00
|
|
|
if (m->payload == NULL) {
|
|
|
|
return IPC_ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
2018-10-04 22:51:31 +02:00
|
|
|
memset (m->payload, 0, length);
|
|
|
|
}
|
2016-12-21 02:56:52 +01:00
|
|
|
|
2018-10-04 22:51:31 +02:00
|
|
|
if (payload != NULL) {
|
|
|
|
memcpy (m->payload, payload, length);
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_NONE;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2019-06-04 01:35:33 +02:00
|
|
|
enum ipc_errors ipc_message_format_data (struct ipc_message *m, char utype, const char *payload, ssize_t length)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
2019-06-04 01:35:33 +02:00
|
|
|
return ipc_message_format (m, MSG_TYPE_DATA, utype, payload, length);
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ipc_message_format_server_close (struct ipc_message *m)
|
2018-10-04 22:51:31 +02:00
|
|
|
{
|
2019-06-04 01:35:33 +02:00
|
|
|
return ipc_message_format (m, MSG_TYPE_SERVER_CLOSE, 0, NULL, 0);
|
2018-10-04 22:51:31 +02:00
|
|
|
}
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
enum ipc_errors ipc_message_empty (struct ipc_message *m)
|
2016-12-21 01:26:47 +01:00
|
|
|
{
|
|
|
|
assert (m != NULL);
|
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
if (m == NULL) {
|
|
|
|
return IPC_ERROR_MESSAGE_EMPTY__EMPTY_MESSAGE_LIST;
|
|
|
|
}
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2018-10-30 13:18:53 +01:00
|
|
|
if (m->payload != NULL) {
|
|
|
|
free (m->payload);
|
|
|
|
m->payload = NULL;
|
|
|
|
}
|
2016-12-21 02:56:52 +01:00
|
|
|
|
2018-10-04 01:54:12 +02:00
|
|
|
m->length = 0;
|
2016-12-21 01:26:47 +01:00
|
|
|
|
2019-06-03 21:25:59 +02:00
|
|
|
return IPC_ERROR_NONE;
|
2016-12-21 01:26:47 +01:00
|
|
|
}
|