GOING 4-BYTE LENGTH, YEAH \o/
This commit is contained in:
parent
48c76930a4
commit
77120450ff
@ -6,7 +6,7 @@
|
|||||||
#define IPC_ERROR_NOT_ENOUGH_MEMORY 100
|
#define IPC_ERROR_NOT_ENOUGH_MEMORY 100
|
||||||
#define IPC_ERROR_WRONG_PARAMETERS 101
|
#define IPC_ERROR_WRONG_PARAMETERS 101
|
||||||
|
|
||||||
// #define IPC_WITH_ERRORS 2
|
// #define IPC_WITH_ERRORS 3
|
||||||
|
|
||||||
#ifdef IPC_WITH_ERRORS
|
#ifdef IPC_WITH_ERRORS
|
||||||
#define handle_error(msg) \
|
#define handle_error(msg) \
|
||||||
|
@ -16,26 +16,26 @@ int ipc_message_format_read (struct ipc_message *m, const char *buf, ssize_t msi
|
|||||||
{
|
{
|
||||||
assert (m != NULL);
|
assert (m != NULL);
|
||||||
assert (buf != NULL);
|
assert (buf != NULL);
|
||||||
assert (msize <= BUFSIZ - 3);
|
assert (msize <= IPC_MAX_MESSAGE_SIZE);
|
||||||
|
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
m->type = buf[0];
|
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
|
#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
|
#endif
|
||||||
assert (m->length == msize - 3 || m->length == 0);
|
assert (m->length == msize - IPC_HEADER_SIZE || m->length == 0);
|
||||||
|
|
||||||
if (m->payload != NULL)
|
if (m->payload != NULL)
|
||||||
free (m->payload), m->payload = NULL;
|
free (m->payload), m->payload = NULL;
|
||||||
|
|
||||||
if (m->payload == NULL && m->length > 0) {
|
if (m->payload == NULL && m->length > 0) {
|
||||||
m->payload = malloc (m->length);
|
m->payload = malloc (m->length);
|
||||||
memcpy (m->payload, buf+3, m->length);
|
memcpy (m->payload, buf+IPC_HEADER_SIZE, m->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -46,7 +46,7 @@ int ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *
|
|||||||
assert (m != NULL);
|
assert (m != NULL);
|
||||||
assert (buf != NULL);
|
assert (buf != NULL);
|
||||||
assert (msize != NULL);
|
assert (msize != NULL);
|
||||||
assert (m->length <= BUFSIZ -3);
|
assert (m->length <= IPC_MAX_MESSAGE_SIZE);
|
||||||
|
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@ -58,19 +58,19 @@ int ipc_message_format_write (const struct ipc_message *m, char **buf, ssize_t *
|
|||||||
return -3;
|
return -3;
|
||||||
|
|
||||||
if (*buf == NULL) {
|
if (*buf == NULL) {
|
||||||
*buf = malloc (3 + m->length);
|
*buf = malloc (IPC_HEADER_SIZE + m->length);
|
||||||
memset (*buf, 0, 3 + m->length);
|
memset (*buf, 0, IPC_HEADER_SIZE + m->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *buffer = *buf;
|
char *buffer = *buf;
|
||||||
|
|
||||||
buffer[0] = m->type;
|
buffer[0] = m->type;
|
||||||
memcpy (buffer + 1, &m->length, 2);
|
memcpy (buffer + 1, &m->length, sizeof m->length);
|
||||||
if (m->payload != NULL) {
|
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
|
#if defined(IPC_WITH_ERRORS) && IPC_WITH_ERRORS > 2
|
||||||
printf ("sending msg: type %u, size %d, msize %ld\n", m->type, m->length, *msize);
|
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);
|
assert (m != NULL);
|
||||||
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
ssize_t msize = BUFSIZ;
|
ssize_t msize = IPC_MAX_MESSAGE_SIZE;
|
||||||
|
|
||||||
int ret = usock_recv (fd, &buf, &msize);
|
int ret = usock_recv (fd, &buf, &msize);
|
||||||
if (ret < 0) {
|
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)
|
int ipc_message_format (struct ipc_message *m, char type, const char *payload, ssize_t length)
|
||||||
{
|
{
|
||||||
assert (m != NULL);
|
assert (m != NULL);
|
||||||
assert (length + 3 <= BUFSIZ);
|
assert (length <= IPC_MAX_MESSAGE_SIZE);
|
||||||
assert ((length == 0 && payload == NULL) || (length > 0 && payload != NULL));
|
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");
|
handle_err ("msg_format_con", "msgsize > BUFSIZ");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ enum msg_types {
|
|||||||
|
|
||||||
struct ipc_message {
|
struct ipc_message {
|
||||||
char type;
|
char type;
|
||||||
unsigned short length;
|
unsigned int length;
|
||||||
char *payload;
|
char *payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
141
core/usocket.c
141
core/usocket.c
@ -20,6 +20,7 @@ int usock_send (const int fd, const char *buf, ssize_t len, ssize_t *sent)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *len is changed to the total message size read (header + payload)
|
||||||
int usock_recv (const int fd, char **buf, ssize_t *len)
|
int usock_recv (const int fd, char **buf, ssize_t *len)
|
||||||
{
|
{
|
||||||
assert(buf != NULL);
|
assert(buf != NULL);
|
||||||
@ -39,75 +40,89 @@ int usock_recv (const int fd, char **buf, ssize_t *len)
|
|||||||
|
|
||||||
if (*buf == NULL) {
|
if (*buf == NULL) {
|
||||||
// do not allocate too much memory
|
// do not allocate too much memory
|
||||||
if (*len > BUFSIZ) {
|
if (*len > IPC_MAX_MESSAGE_SIZE) {
|
||||||
handle_err ("usock_recv", "len > BUFSIZ");
|
handle_err ("usock_recv", "len > IPC_MAX_MESSAGE_SIZE");
|
||||||
|
*len = IPC_MAX_MESSAGE_SIZE;
|
||||||
}
|
}
|
||||||
if (*len == 0)
|
*buf = malloc (*len + IPC_HEADER_SIZE);
|
||||||
*len = BUFSIZ;
|
|
||||||
*buf = malloc ((*len < BUFSIZ) ? *len : BUFSIZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = recv (fd, *buf, *len, 0);
|
unsigned int msize = 0;
|
||||||
if (ret < 0) {
|
unsigned int msize_read = 0;
|
||||||
if (*buf != NULL)
|
|
||||||
free (*buf);
|
|
||||||
|
|
||||||
handle_err ("usock_recv", "recv ret < 0");
|
do {
|
||||||
perror("recv");
|
ret = recv (fd, *buf, *len, 0);
|
||||||
*len = 0;
|
if (msize == 0) {
|
||||||
|
memcpy (&msize, *buf + 1, sizeof msize);
|
||||||
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;
|
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
|
// 1 on none byte received, indicates a closed recipient
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#define TMPDIR "/run/ipc/"
|
#define TMPDIR "/run/ipc/"
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
|
|
||||||
|
#define IPC_HEADER_SIZE 5
|
||||||
|
#define IPC_MAX_MESSAGE_SIZE 8000000-IPC_HEADER_SIZE
|
||||||
|
|
||||||
struct ipc_service {
|
struct ipc_service {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#define SERVICE_NAME "pongd"
|
#define SERVICE_NAME "pongd"
|
||||||
|
|
||||||
|
#define MAX_MESSAGE_SIZE 20000
|
||||||
|
|
||||||
void interactive (char * service_name, char *env[])
|
void interactive (char * service_name, char *env[])
|
||||||
{
|
{
|
||||||
struct ipc_message m;
|
struct ipc_message m;
|
||||||
@ -30,16 +32,24 @@ void interactive (char * service_name, char *env[])
|
|||||||
char msg_type = 0;
|
char msg_type = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
#if 0 // version with readline, slow, valgrind-incompatible
|
||||||
|
|
||||||
char * mtype_str = readline("msg type: ");
|
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);
|
free(mtype_str);
|
||||||
|
|
||||||
char * buf = readline ("msg: ");
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ipc_message_format (&m, msg_type, buf, strlen(buf));
|
ipc_message_format (&m, msg_type, buf, strlen(buf));
|
||||||
memset (buf, 0, BUFSIZ);
|
free (buf);
|
||||||
|
|
||||||
// print_msg (&m);
|
// print_msg (&m);
|
||||||
|
|
||||||
@ -54,27 +64,71 @@ void interactive (char * service_name, char *env[])
|
|||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("msg recv: %s", m.payload);
|
printf ("\nmsg recv: %s", m.payload);
|
||||||
ipc_message_empty (&m);
|
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) {
|
if (ipc_application_close (&srv) < 0) {
|
||||||
handle_err("main", "application_close < 0");
|
handle_err("main", "application_close < 0");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
ipc_message_empty (&m);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[], char *env[])
|
int main (int argc, char *argv[], char *env[])
|
||||||
{
|
{
|
||||||
argc = argc; // warnings
|
|
||||||
argv = argv; // warnings
|
|
||||||
|
|
||||||
char service_name[100];
|
char service_name[100];
|
||||||
|
memset (service_name, 0, 100);
|
||||||
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
ssize_t t = strlen(argv[1]) > 100 ? 100 : strlen(argv[1]);
|
ssize_t t = strlen(argv[1]) > 100 ? 100 : strlen(argv[1]);
|
||||||
memcpy(service_name, argv[1], t);
|
memcpy(service_name, argv[1], t);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
memcpy(service_name, SERVICE_NAME, strlen(SERVICE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
interactive (service_name, env);
|
interactive (service_name, env);
|
||||||
|
|
||||||
|
@ -91,7 +91,9 @@ void handle_new_msg (struct ipc_clients *clients, struct ipc_clients *clients_ta
|
|||||||
exit (0);
|
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) {
|
if (ipc_server_write (pc, &m) < 0) {
|
||||||
handle_err( "handle_new_msg", "server_write < 0");
|
handle_err( "handle_new_msg", "server_write < 0");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user