2019-07-27 15:46:04 +02:00
|
|
|
|
#include <sys/select.h>
|
2020-07-13 14:12:08 +02:00
|
|
|
|
#include <sys/time.h>
|
2018-10-28 18:12:17 +01:00
|
|
|
|
#include <unistd.h>
|
2016-12-17 18:00:04 +01:00
|
|
|
|
|
2016-05-30 01:54:19 +02:00
|
|
|
|
#include <stdio.h>
|
2020-01-01 12:11:34 +01:00
|
|
|
|
#include <errno.h> // error numbers
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2019-07-27 15:46:04 +02:00
|
|
|
|
#include "ipc.h"
|
|
|
|
|
#include "utils.h"
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2019-07-27 15:46:04 +02:00
|
|
|
|
// print structures
|
|
|
|
|
#include "message.h"
|
2019-06-12 15:02:43 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
#include <fcntl.h>
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int fd_is_valid(int fd)
|
2019-06-03 21:25:59 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
|
2016-06-12 12:38:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
struct ipc_error ipc_server_init (struct ipc_ctx *ctx, const char *sname)
|
2016-05-26 18:27:59 +02:00
|
|
|
|
{
|
2020-01-01 12:11:34 +01:00
|
|
|
|
T_R ((sname == NULL), IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM);
|
2016-05-26 18:27:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Declaration and instanciation of the new connection (ipc_connection_info + pollfd).
|
|
|
|
|
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
|
|
|
|
srv.type = IPC_CONNECTION_TYPE_SERVER;
|
|
|
|
|
SECURE_DECLARATION(struct pollfd, pollfd);
|
|
|
|
|
pollfd.events = POLLIN;
|
2016-06-12 14:41:25 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Get the service path.
|
2020-01-01 12:11:34 +01:00
|
|
|
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
2020-01-01 12:11:34 +01:00
|
|
|
|
size_t s = strlen (buf);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
if (s > PATH_MAX)
|
|
|
|
|
s = PATH_MAX;
|
|
|
|
|
SECURE_BUFFER_HEAP_ALLOCATION_R (srv.spath, s + 1,, IPC_ERROR_SERVER_INIT__MALLOC);
|
|
|
|
|
memcpy (srv.spath, buf, s);
|
|
|
|
|
srv.spath[s] = '\0'; // to be sure
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Socket initialisation for the service.
|
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (usock_init (&pollfd.fd, srv.spath));
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Add the server to the listened file descriptors.
|
|
|
|
|
// ipc_add allocate memory then copy the data of srv and pollfd in ctx.
|
|
|
|
|
TEST_IPC_RR (ipc_add (ctx, &srv, &pollfd), "cannot add the server in the context");
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// when ipcd is not working properly (or do not retrieve the service): srv->fd = 0
|
|
|
|
|
struct ipc_error ipc_contact_ipcd (int *pfd, const char *sname)
|
2019-07-27 15:46:04 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((pfd == NULL), IPC_ERROR_CONTACT_IPCD__NO_FD_PARAM);
|
|
|
|
|
T_R ((sname == NULL), IPC_ERROR_CONTACT_IPCD__NO_SERVICE_NAME_PARAM);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-11-05 14:15:39 +01:00
|
|
|
|
// In case there is a problem with ipcd.
|
|
|
|
|
*pfd = 0;
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
char *ipcd_var = getenv ("IPC_NETWORK");
|
|
|
|
|
if (ipcd_var == NULL) {
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2018-10-08 15:18:56 +02:00
|
|
|
|
}
|
2020-01-01 12:11:34 +01:00
|
|
|
|
// TODO: is there another, more interesting way to do this?
|
|
|
|
|
// currently, IPC_NETWORK is shared with the network service
|
|
|
|
|
// in order to route requests over any chosen protocol stack
|
|
|
|
|
// ex: IPC_NETWORK="audio tor://some.example.com/audio ;pong tls://pong.example.com/pong"
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
|
|
|
|
SECURE_BUFFER_DECLARATION (char, columnthensname, BUFSIZ);
|
|
|
|
|
columnthensname[0] = ';';
|
2020-01-01 12:11:34 +01:00
|
|
|
|
memcpy (columnthensname + 1, sname, strlen (sname));
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
if (strncmp (ipcd_var, sname, strlen (sname)) != 0 && strstr (ipcd_var, columnthensname) == NULL) {
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2018-10-08 15:18:56 +02:00
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Get the service path.
|
2020-01-01 12:11:34 +01:00
|
|
|
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RR (service_path (buf, "network"), "cannot get network service path");
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int ipcd_fd = 0;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (usock_connect (&ipcd_fd, buf));
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
|
|
|
|
SECURE_DECLARATION (struct ipc_message, msg);
|
|
|
|
|
msg.type = MSG_TYPE_NETWORK_LOOKUP;
|
|
|
|
|
msg.user_type = MSG_TYPE_NETWORK_LOOKUP;
|
2016-12-19 19:20:27 +01:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
SECURE_BUFFER_DECLARATION (char, content, BUFSIZ);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
snprintf (content, BUFSIZ, "%s;%s", sname, ipcd_var);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
|
|
|
|
msg.length = strlen (content);
|
|
|
|
|
msg.payload = content;
|
|
|
|
|
|
2020-11-05 14:15:39 +01:00
|
|
|
|
TEST_IPC_RR (ipc_write_fd (ipcd_fd, &msg), "cannot send a message to ipcd");
|
|
|
|
|
|
|
|
|
|
memset (&msg, 0, sizeof(struct ipc_message));
|
|
|
|
|
|
|
|
|
|
// ipcd successfully contacted the service or failed.
|
|
|
|
|
// ipcd will tell either OK or NOT OK.
|
|
|
|
|
TEST_IPC_RR (ipc_read_fd (ipcd_fd, &msg), "cannot read the ipcd response");
|
|
|
|
|
|
|
|
|
|
// In case ipcd failed.
|
|
|
|
|
if (msg.length != 2) {
|
|
|
|
|
printf ("ipcd failed to contact service: (%d bytes) %s\n"
|
|
|
|
|
, msg.length
|
|
|
|
|
, msg.payload);
|
|
|
|
|
SECURE_DECLARATION(struct ipc_error, ret);
|
|
|
|
|
ret.error_code = IPC_ERROR_CLOSED_RECIPIENT;
|
|
|
|
|
usock_close (ipcd_fd);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error ret = ipc_receive_fd (ipcd_fd, pfd);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
if (ret.error_code == IPC_ERROR_NONE) {
|
2020-07-13 14:12:08 +02:00
|
|
|
|
usock_close (ipcd_fd);
|
2019-06-03 21:25:59 +02:00
|
|
|
|
}
|
2016-05-26 18:27:59 +02:00
|
|
|
|
|
2019-07-27 15:46:04 +02:00
|
|
|
|
return ret;
|
2016-12-19 18:16:38 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Create context, contact ipcd, connects to the service.
|
|
|
|
|
struct ipc_error ipc_connection_ (struct ipc_ctx *ctx, const char *sname, enum ipc_connection_type type, int *serverfd)
|
2016-06-10 01:21:04 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_CONNECTION__NO_CTX);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
SECURE_DECLARATION(struct ipc_connection_info, srv);
|
|
|
|
|
srv.type = type;
|
|
|
|
|
SECURE_DECLARATION(struct pollfd, pollfd);
|
|
|
|
|
pollfd.events = POLLIN;
|
|
|
|
|
|
2020-11-05 14:15:39 +01:00
|
|
|
|
TEST_IPC_P (ipc_contact_ipcd (&pollfd.fd, sname), "error during ipcd connection");
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// if ipcd did not initiate the connection
|
|
|
|
|
if (pollfd.fd <= 0) {
|
2020-01-01 12:11:34 +01:00
|
|
|
|
// gets the service path
|
|
|
|
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (usock_connect (&pollfd.fd, buf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the server to the listened file descriptors.
|
|
|
|
|
TEST_IPC_RR (ipc_add (ctx, &srv, &pollfd), "cannot add the server in the context");
|
|
|
|
|
|
|
|
|
|
if (serverfd != NULL) {
|
|
|
|
|
*serverfd = pollfd.fd;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2016-10-28 13:58:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2016-06-10 01:21:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int ipc_ctx_fd_type (struct ipc_ctx *ctx, int fd, enum ipc_connection_type type)
|
|
|
|
|
{
|
|
|
|
|
if (ctx == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
|
|
|
|
if (ctx->pollfd[i].fd == fd) {
|
|
|
|
|
ctx->cinfos[i].type = type;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 18:37:33 +02:00
|
|
|
|
struct ipc_error ipc_connection (struct ipc_ctx *ctx, const char *sname, int *serverfd)
|
2020-07-13 14:12:08 +02:00
|
|
|
|
{
|
|
|
|
|
// Data received on the socket = messages, not new clients, and not switched (no callbacks).
|
2020-07-13 18:37:33 +02:00
|
|
|
|
return ipc_connection_ (ctx, sname, IPC_CONNECTION_TYPE_IPC, serverfd);
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ipc_error ipc_connection_switched (struct ipc_ctx *ctx, const char *sname, int clientfd, int *serverfd)
|
2016-05-26 18:27:59 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int sfd = 0;
|
|
|
|
|
// Data received are for switched fd (callbacks should be used).
|
|
|
|
|
struct ipc_error ret = ipc_connection_ (ctx
|
|
|
|
|
, sname
|
|
|
|
|
, IPC_CONNECTION_TYPE_SWITCHED
|
|
|
|
|
, &sfd);
|
|
|
|
|
|
|
|
|
|
if (ret.error_code != IPC_ERROR_NONE) {
|
|
|
|
|
return ret;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
if (serverfd != NULL) {
|
|
|
|
|
*serverfd = sfd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ipc_add_fd_switched (ctx, clientfd);
|
|
|
|
|
// ipc_ctx_fd_type (ctx, clientfd, IPC_CONNECTION_TYPE_SWITCHED);
|
|
|
|
|
ipc_ctx_switching_add (ctx, clientfd, sfd);
|
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
return ret;
|
2016-05-26 18:27:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error ipc_close_all (struct ipc_ctx *ctx)
|
|
|
|
|
{
|
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_CLOSE_ALL__NO_CTX_PARAM);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0 ; i < ctx->size ; i++) {
|
2020-11-06 21:17:01 +01:00
|
|
|
|
TEST_IPC_P (ipc_close (ctx, i), "cannot close a connection in ipc_close_all");
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IPC_RETURN_NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 02:47:08 +02:00
|
|
|
|
// Removing all messages for this fd.
|
|
|
|
|
void ipc_remove_messages_for_fd (struct ipc_ctx *ctx, int fd)
|
|
|
|
|
{
|
|
|
|
|
struct ipc_message *m = NULL;
|
|
|
|
|
size_t looping_count = ctx->tx.size;
|
|
|
|
|
for (size_t i = 0; i < looping_count; i++) {
|
|
|
|
|
m = &ctx->tx.messages[i];
|
|
|
|
|
if (m->fd == fd) {
|
|
|
|
|
// Freeing the message structure.
|
|
|
|
|
ipc_message_empty (m);
|
|
|
|
|
ipc_messages_del (&ctx->tx, i); // remove the message indexed by i
|
|
|
|
|
// Let restart this round
|
|
|
|
|
i--;
|
|
|
|
|
looping_count--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error ipc_close (struct ipc_ctx *ctx, uint32_t index)
|
2019-06-03 21:25:59 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_CLOSE__NO_CTX_PARAM);
|
|
|
|
|
|
|
|
|
|
SECURE_DECLARATION (struct ipc_error, ret);
|
|
|
|
|
int fd = ctx->pollfd[index].fd;
|
|
|
|
|
|
|
|
|
|
// Closing the file descriptor only if it is not an external connection,
|
|
|
|
|
// this should be handled by the libipc user application.
|
|
|
|
|
if (ctx->cinfos[index].type != IPC_CONNECTION_TYPE_EXTERNAL) {
|
|
|
|
|
ret = usock_close (fd);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 02:47:08 +02:00
|
|
|
|
// Remove all messages for this fd.
|
|
|
|
|
ipc_remove_messages_for_fd (ctx, fd);
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Verify that the close was OK.
|
|
|
|
|
if (ret.error_code != IPC_ERROR_NONE) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ctx->cinfos[index].type == IPC_CONNECTION_TYPE_SERVER) {
|
|
|
|
|
ret = usock_remove (ctx->cinfos[index].spath);
|
|
|
|
|
if (ctx->cinfos[index].spath != NULL) {
|
|
|
|
|
free (ctx->cinfos[index].spath);
|
|
|
|
|
ctx->cinfos[index].spath = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2016-05-26 18:27:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// New connection from a client.
|
|
|
|
|
struct ipc_error ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
2016-05-26 18:27:59 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM);
|
|
|
|
|
T_R ((index >= ctx->size), IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX);
|
2016-12-20 23:36:00 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Memory reallocation.
|
|
|
|
|
ipc_ctx_new_alloc (ctx);
|
|
|
|
|
|
|
|
|
|
int server_fd = ctx->pollfd[index].fd;
|
|
|
|
|
int *client_fd = &ctx->pollfd[ctx->size -1].fd;
|
|
|
|
|
|
|
|
|
|
TEST_IPC_RR (usock_accept (server_fd, client_fd), "cannot accept IPC connection");
|
|
|
|
|
ctx->pollfd[ctx->size -1].events = POLLIN; // Tell to poll(2) to watch for incoming data from this fd.
|
|
|
|
|
ctx->cinfos[ctx->size -1].type = IPC_CONNECTION_TYPE_IPC;
|
|
|
|
|
|
|
|
|
|
// Set the event structure.
|
|
|
|
|
uint32_t client_index = ctx->size - 1;
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, client_index, *client_fd, NULL);
|
2016-12-20 23:36:00 +01:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
}
|
2017-01-19 22:07:52 +01:00
|
|
|
|
|
2019-07-27 15:46:04 +02:00
|
|
|
|
// receive then format in an ipc_message structure
|
2020-07-14 16:10:18 +02:00
|
|
|
|
struct ipc_error ipc_read_fd (int32_t fd, struct ipc_message *m)
|
2019-07-27 15:46:04 +02:00
|
|
|
|
{
|
2020-01-01 12:11:34 +01:00
|
|
|
|
T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
|
2017-01-19 22:07:52 +01:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
size_t msize = IPC_MAX_MESSAGE_SIZE;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
SECURE_BUFFER_DECLARATION (char, buf, msize);
|
|
|
|
|
char *pbuf = buf;
|
2019-06-12 15:02:43 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// On error or closed recipient, the buffer already freed.
|
2020-07-14 16:10:18 +02:00
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (usock_recv (fd, &pbuf, &msize));
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (ipc_message_format_read (m, buf, msize));
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR; // propagates ipc_message_format return
|
2017-01-19 22:07:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-14 16:10:18 +02:00
|
|
|
|
struct ipc_error ipc_read (const struct ipc_ctx *ctx, uint32_t index, struct ipc_message *m)
|
|
|
|
|
{
|
|
|
|
|
return ipc_read_fd (ctx->pollfd[index].fd, m);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
struct ipc_error ipc_write_fd (int fd, const struct ipc_message *m)
|
2018-10-28 17:09:35 +01:00
|
|
|
|
{
|
2020-01-01 12:11:34 +01:00
|
|
|
|
size_t msize = 0;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
SECURE_BUFFER_DECLARATION (char, buf, IPC_MAX_MESSAGE_SIZE);
|
|
|
|
|
char *pbuf = buf;
|
|
|
|
|
|
|
|
|
|
ipc_message_format_write (m, &pbuf, &msize);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
size_t nbytes_sent = 0;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_RETURN_ON_ERROR (usock_send (fd, buf, msize, &nbytes_sent));
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
// what was sent != what should have been sent
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((nbytes_sent != msize), IPC_ERROR_WRITE_FD__NOT_ENOUGH_DATA);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2018-10-28 17:09:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Put the message in the list of messages to send.
|
|
|
|
|
struct ipc_error ipc_write (struct ipc_ctx *ctx, const struct ipc_message *m)
|
2016-12-22 21:48:35 +01:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int found = 0;
|
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
|
|
|
|
if (ctx->pollfd[i].fd == m->fd) {
|
|
|
|
|
ctx->pollfd[i].events |= POLLOUT;
|
|
|
|
|
found = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T_R ((found == 0), IPC_ERROR_WRITE__FD_NOT_FOUND);
|
|
|
|
|
|
|
|
|
|
// Performs a deep copy of the structure.
|
|
|
|
|
return ipc_messages_add (&ctx->tx, m);
|
2018-10-05 22:33:43 +02:00
|
|
|
|
}
|
2018-10-10 23:08:58 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
/**
|
|
|
|
|
* Allocate memory then add a new connection to the context.
|
|
|
|
|
*/
|
|
|
|
|
struct ipc_error ipc_add (struct ipc_ctx *ctx, struct ipc_connection_info *p, struct pollfd *pollfd)
|
2019-07-27 15:46:04 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
|
|
|
|
|
T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
|
|
|
|
|
T_R ((pollfd == NULL), IPC_ERROR_ADD__NO_PARAM_POLLFD);
|
|
|
|
|
|
|
|
|
|
// Memory reallocation.
|
|
|
|
|
ipc_ctx_new_alloc (ctx);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx->size <= 0), IPC_ERROR_ADD__NOT_ENOUGH_MEMORY);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
ctx->cinfos[ctx->size - 1] = *p;
|
|
|
|
|
ctx->pollfd[ctx->size - 1] = *pollfd;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error ipc_del (struct ipc_ctx *ctx, uint32_t index)
|
2019-07-27 15:46:04 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
|
|
|
|
|
T_R ((ctx->cinfos == NULL || ctx->pollfd == NULL), IPC_ERROR_DEL__EMPTY_LIST);
|
|
|
|
|
T_R ((index >= ctx->size), IPC_ERROR_DEL__CANNOT_FIND_CLIENT);
|
|
|
|
|
|
|
|
|
|
if (ctx->cinfos[index].spath != NULL) {
|
|
|
|
|
free (ctx->cinfos[index].spath);
|
|
|
|
|
ctx->cinfos[index].spath = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 02:47:08 +02:00
|
|
|
|
ipc_remove_messages_for_fd (ctx, ctx->pollfd[index].fd);
|
2020-07-21 00:10:42 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
ctx->size--;
|
|
|
|
|
|
|
|
|
|
if (ctx->size == 0) {
|
|
|
|
|
// free ctx->cinfos and ctx->pollfd
|
|
|
|
|
ipc_ctx_free (ctx);
|
|
|
|
|
IPC_RETURN_NO_ERROR;
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// The last element in the array replaces the removed one.
|
|
|
|
|
ctx->cinfos[index] = ctx->cinfos[ctx->size];
|
|
|
|
|
ctx->pollfd[index] = ctx->pollfd[ctx->size];
|
|
|
|
|
|
|
|
|
|
// Reallocation of the arrays. TODO: should be optimised someday.
|
|
|
|
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
|
|
|
|
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
|
|
|
|
|
|
|
|
|
if (ctx->cinfos == NULL || ctx->pollfd == NULL) {
|
|
|
|
|
IPC_RETURN_ERROR (IPC_ERROR_DEL__EMPTIED_LIST);
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error ipc_add_fd_ (struct ipc_ctx *ctx, int fd, enum ipc_connection_type type)
|
2018-10-10 23:08:58 +02:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
SECURE_DECLARATION (struct ipc_connection_info, cinfo);
|
|
|
|
|
cinfo.type = type;
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
SECURE_DECLARATION (struct pollfd, pollfd);
|
|
|
|
|
pollfd.fd = fd;
|
|
|
|
|
pollfd.events = POLLIN;
|
2018-10-10 23:08:58 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
return ipc_add (ctx, &cinfo, &pollfd);
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// add a switched file descriptor to read
|
|
|
|
|
struct ipc_error ipc_add_fd_switched (struct ipc_ctx *ctx, int fd)
|
|
|
|
|
{
|
|
|
|
|
return ipc_add_fd_ (ctx, fd, IPC_CONNECTION_TYPE_SWITCHED);
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// add an arbitrary file descriptor to read
|
|
|
|
|
struct ipc_error ipc_add_fd (struct ipc_ctx *ctx, int fd)
|
|
|
|
|
{
|
|
|
|
|
return ipc_add_fd_ (ctx, fd, IPC_CONNECTION_TYPE_EXTERNAL);
|
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// remove a connection from its file descriptor
|
|
|
|
|
struct ipc_error ipc_del_fd (struct ipc_ctx *ctx, int fd)
|
|
|
|
|
{
|
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
|
|
|
|
|
T_R ((ctx->cinfos == NULL || ctx->pollfd == NULL), IPC_ERROR_DEL_FD__EMPTY_LIST);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
|
|
|
|
if (ctx->pollfd[i].fd == fd) {
|
|
|
|
|
return ipc_del (ctx, i);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
}
|
2018-10-10 23:08:58 +02:00
|
|
|
|
}
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ipc_error handle_writing_message (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
|
|
|
|
{
|
|
|
|
|
int txfd = ctx->pollfd[index].fd;
|
|
|
|
|
int mfd;
|
|
|
|
|
struct ipc_message *m;
|
|
|
|
|
for (size_t i = 0; ctx->tx.size ; i++) {
|
|
|
|
|
m = &ctx->tx.messages[i];
|
|
|
|
|
mfd = m->fd;
|
|
|
|
|
if (txfd == mfd) {
|
2020-10-01 02:47:08 +02:00
|
|
|
|
// In case the writing is compromised, do not return right away,
|
|
|
|
|
// just print the result.
|
|
|
|
|
TEST_IPC_P(ipc_write_fd (txfd, m), "cannot send a message to the client");
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
// Freeing the message structure.
|
|
|
|
|
ipc_message_empty (m);
|
|
|
|
|
// Removing the message from the context.
|
|
|
|
|
ipc_messages_del (&ctx->tx, i); // remove the message indexed by i
|
|
|
|
|
|
|
|
|
|
break; // The message has been sent
|
|
|
|
|
}
|
2018-10-10 23:08:58 +02:00
|
|
|
|
}
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TX, index, ctx->pollfd[index].fd, NULL);
|
|
|
|
|
IPC_RETURN_NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ipc_error handle_new_message (struct ipc_event *event, struct ipc_ctx *ctx, int index)
|
|
|
|
|
{
|
2020-01-01 12:11:34 +01:00
|
|
|
|
SECURE_DECLARATION (struct ipc_error, ret);
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Listen to what they have to say (disconnection or message)
|
|
|
|
|
// then add a client to `event`, the ipc_event structure.
|
|
|
|
|
struct ipc_message *m = NULL;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
SECURE_BUFFER_HEAP_ALLOCATION_R (m, sizeof (struct ipc_message),, IPC_ERROR_HANDLE_MESSAGE__NOT_ENOUGH_MEMORY);
|
|
|
|
|
|
|
|
|
|
// current talking client
|
2020-07-13 14:12:08 +02:00
|
|
|
|
ret = ipc_read (ctx, index, m);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
if (ret.error_code != IPC_ERROR_NONE && ret.error_code != IPC_ERROR_CLOSED_RECIPIENT) {
|
|
|
|
|
struct ipc_error rvalue = ret; // store the final return value
|
2020-11-08 06:07:28 +01:00
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
ipc_message_empty (m);
|
|
|
|
|
free (m);
|
|
|
|
|
|
2022-02-04 02:43:49 +01:00
|
|
|
|
int fd = ctx->pollfd[index].fd;
|
|
|
|
|
|
2020-11-08 06:07:28 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf ("error when ipc_read: index %d fd %d error num %d, message: %s\n"
|
2022-02-04 02:43:49 +01:00
|
|
|
|
, index, fd
|
2020-11-08 06:07:28 +01:00
|
|
|
|
, ret.error_code
|
|
|
|
|
, ret.error_message);
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
// if there is a problem, just remove the client
|
2020-07-13 14:12:08 +02:00
|
|
|
|
TEST_IPC_P (ipc_close (ctx, index), "cannot close a connection in handle_message");
|
|
|
|
|
TEST_IPC_P (ipc_del (ctx, index), "cannot delete a connection in handle_message");
|
2020-01-01 12:11:34 +01:00
|
|
|
|
|
2022-02-04 02:43:49 +01:00
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, index, fd, NULL);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
return rvalue;
|
|
|
|
|
}
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
// disconnection: close the client then delete it from ctx
|
2020-01-01 12:11:34 +01:00
|
|
|
|
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
2020-07-13 14:12:08 +02:00
|
|
|
|
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, index, ctx->pollfd[index].fd, NULL);
|
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
ipc_message_empty (m);
|
|
|
|
|
free (m);
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-11-08 01:19:02 +01:00
|
|
|
|
TEST_IPC_P (ipc_close (ctx, index), "cannot close a connection on closed recipient in handle_message");
|
|
|
|
|
TEST_IPC_P (ipc_del (ctx, index), "cannot delete a connection on closed recipient in handle_message");
|
|
|
|
|
|
2020-01-01 12:11:34 +01:00
|
|
|
|
// warning: do not forget to free the ipc_client structure
|
|
|
|
|
IPC_RETURN_NO_ERROR;
|
|
|
|
|
}
|
2018-10-28 17:09:35 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// The message carries the fd it was received on.
|
|
|
|
|
m->fd = ctx->pollfd[index].fd;
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_MESSAGE, index, ctx->pollfd[index].fd, m);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
IPC_RETURN_NO_ERROR;
|
2018-10-28 17:09:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error
|
|
|
|
|
handle_writing_switched_message (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
2018-10-28 17:09:35 +01:00
|
|
|
|
{
|
2020-07-13 14:12:08 +02:00
|
|
|
|
return fd_switching_write (event, ctx, index);
|
|
|
|
|
}
|
2018-10-28 17:09:35 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct ipc_error
|
|
|
|
|
handle_switched_message(struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
|
|
|
|
{
|
|
|
|
|
return fd_switching_read (event, ctx, index);
|
|
|
|
|
}
|
2018-10-28 17:09:35 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
/* timer is in ms */
|
|
|
|
|
struct ipc_error ipc_wait_event (struct ipc_ctx *ctx, struct ipc_event *event, int *timer)
|
|
|
|
|
{
|
|
|
|
|
T_R ((ctx == NULL), IPC_ERROR_WAIT_EVENT__NO_CLIENTS_PARAM);
|
|
|
|
|
T_R ((event == NULL), IPC_ERROR_WAIT_EVENT__NO_EVENT_PARAM);
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
IPC_EVENT_CLEAN (event);
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
// By default, everything is alright.
|
|
|
|
|
SECURE_DECLARATION(struct ipc_error, final_return);
|
|
|
|
|
final_return.error_code = IPC_ERROR_NONE;
|
|
|
|
|
|
2020-08-03 00:42:34 +02:00
|
|
|
|
int32_t n = 0;
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-21 00:10:42 +02:00
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
|
|
|
|
// We assume that any fd in the list has to be listen to.
|
2020-11-08 06:07:28 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf ("reading fd: %d index %lu\n", ctx->pollfd[i].fd, i);
|
|
|
|
|
#endif
|
2020-07-21 00:10:42 +02:00
|
|
|
|
ctx->pollfd[i].events = POLLIN;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
// For each message to send…
|
2020-07-13 14:12:08 +02:00
|
|
|
|
for (size_t i = 0; i < ctx->tx.size; i++) {
|
2020-11-06 21:17:01 +01:00
|
|
|
|
// … verify that its destination is available for message exchange.
|
2020-07-13 14:12:08 +02:00
|
|
|
|
for (size_t y = 0; y < ctx->size; y++) {
|
|
|
|
|
if (ctx->pollfd[y].fd == ctx->tx.messages[i].fd) {
|
2020-11-08 06:07:28 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf ("writing fd: %d\n", ctx->pollfd[y].fd);
|
|
|
|
|
#endif
|
2020-07-13 14:12:08 +02:00
|
|
|
|
ctx->pollfd[y].events |= POLLOUT;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct timeval tv_1;
|
|
|
|
|
memset (&tv_1, 0, sizeof(struct timeval));
|
2018-10-28 17:09:35 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
struct timeval tv_2;
|
|
|
|
|
memset (&tv_2, 0, sizeof(struct timeval));
|
2019-10-26 18:17:20 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
gettimeofday(&tv_1, NULL);
|
2019-10-26 18:17:20 +02:00
|
|
|
|
|
2020-08-03 00:42:34 +02:00
|
|
|
|
int timer_ = *timer;
|
|
|
|
|
|
|
|
|
|
/* In case there is a file descriptor that requires more to read. */
|
2020-10-01 01:27:33 +02:00
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
2020-08-03 00:42:34 +02:00
|
|
|
|
if (ctx->cinfos[i].more_to_read == 1) {
|
|
|
|
|
// printf ("There is more to read for _at least_ fd %d\n", ctx->pollfd[i].fd);
|
|
|
|
|
timer_ = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((n = poll(ctx->pollfd, ctx->size, timer_)) < 0) {
|
2020-07-13 14:12:08 +02:00
|
|
|
|
IPC_RETURN_ERROR (IPC_ERROR_WAIT_EVENT__POLL);
|
2019-10-26 18:17:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
gettimeofday(&tv_2, NULL);
|
2019-10-26 18:17:20 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
int nb_sec_ms = (tv_2.tv_sec - tv_1.tv_sec) * 1000;
|
|
|
|
|
int nb_usec_ms = (tv_2.tv_usec - tv_1.tv_usec) / 1000;
|
|
|
|
|
int time_elapsed_ms = (nb_sec_ms + nb_usec_ms);
|
2020-01-01 12:11:34 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Handle memory fuckery, 'cause low level programming is fun.
|
|
|
|
|
if (time_elapsed_ms >= *timer) {
|
|
|
|
|
*timer = 0;
|
2019-10-26 18:17:20 +02:00
|
|
|
|
}
|
2020-07-13 14:12:08 +02:00
|
|
|
|
else {
|
|
|
|
|
*timer -= time_elapsed_ms;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Timeout.
|
2020-08-03 00:42:34 +02:00
|
|
|
|
if (n == 0 && timer_ != 0) {
|
2020-07-13 14:12:08 +02:00
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_TIMER, 0, 0, NULL);
|
|
|
|
|
IPC_RETURN_NO_ERROR;
|
|
|
|
|
}
|
2020-01-01 12:11:34 +01:00
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
for (size_t i = 0; i < ctx->size; i++) {
|
|
|
|
|
|
|
|
|
|
// Whatever happens, we have the fd and the index in event.
|
|
|
|
|
event->index = i;
|
|
|
|
|
event->origin = ctx->pollfd[i].fd;
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Something to read or connection.
|
2020-08-03 00:42:34 +02:00
|
|
|
|
if (ctx->pollfd[i].revents & POLLIN || ctx->cinfos[i].more_to_read == 1) {
|
|
|
|
|
|
|
|
|
|
// Avoiding loops.
|
|
|
|
|
ctx->cinfos[i].more_to_read = 0;
|
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// In case there is something to read for the server socket: new client.
|
|
|
|
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SERVER) {
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = ipc_accept_add (event, ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// fd is switched: using callbacks for IO operations.
|
|
|
|
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SWITCHED) {
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = handle_switched_message (event, ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2018-10-28 18:12:17 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// No treatment of the socket if external socket: the libipc user should handle IO operations.
|
|
|
|
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_EXTERNAL) {
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_EXTRA_SOCKET, i, ctx->pollfd[i].fd, NULL);
|
2020-11-06 21:17:01 +01:00
|
|
|
|
// Default: return no error.
|
|
|
|
|
goto wait_event_exit;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = handle_new_message (event, ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2019-07-27 15:46:04 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Something can be sent.
|
|
|
|
|
if (ctx->pollfd[i].revents & POLLOUT) {
|
|
|
|
|
ctx->pollfd[i].events &= ~POLLOUT;
|
2018-10-28 18:12:17 +01:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// fd is switched: using callbacks for IO operations.
|
|
|
|
|
if (ctx->cinfos[i].type == IPC_CONNECTION_TYPE_SWITCHED) {
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = handle_writing_switched_message (event, ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
2018-10-28 18:12:17 +01:00
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = handle_writing_message (event, ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
2020-01-01 12:11:34 +01:00
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
// Disconnection.
|
|
|
|
|
if (ctx->pollfd[i].revents & POLLHUP) {
|
|
|
|
|
/** IPC_EVENT_SET: event, type, index, fd, message */
|
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_DISCONNECTION, i, ctx->pollfd[i].fd, NULL);
|
2020-11-06 21:17:01 +01:00
|
|
|
|
final_return = ipc_close (ctx, i);
|
|
|
|
|
goto wait_event_exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ctx->pollfd[i].revents & POLLERR) {
|
2020-11-08 06:07:28 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf ("pollerr: problem with fd %d\n", ctx->pollfd[i].fd);
|
|
|
|
|
#endif
|
2020-11-06 21:17:01 +01:00
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, i, ctx->pollfd[i].fd, NULL);
|
|
|
|
|
goto wait_event_exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ctx->pollfd[i].revents & POLLNVAL) {
|
2020-11-08 06:07:28 +01:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
printf ("pollnval: invalid fd %d\n", ctx->pollfd[i].fd);
|
|
|
|
|
#endif
|
2020-11-06 21:17:01 +01:00
|
|
|
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, i, ctx->pollfd[i].fd, NULL);
|
|
|
|
|
goto wait_event_exit;
|
2020-07-13 14:12:08 +02:00
|
|
|
|
}
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-07-13 14:12:08 +02:00
|
|
|
|
} /** for loop: end of the message handling */
|
2019-06-03 21:25:59 +02:00
|
|
|
|
|
2020-11-06 21:17:01 +01:00
|
|
|
|
printf ("END OF THE LOOP WITHOUT GOTO!\n");
|
|
|
|
|
|
|
|
|
|
wait_event_exit:
|
|
|
|
|
|
|
|
|
|
/** TODO: tests on event, it has to be filled. */
|
|
|
|
|
if (event->type == 0) {
|
|
|
|
|
printf ("EVENT TYPE NOT FILLED! code: %d, error_message: %s\n"
|
|
|
|
|
, final_return.error_code
|
|
|
|
|
, final_return.error_message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return final_return;
|
2019-06-03 21:25:59 +02:00
|
|
|
|
}
|